├── src ├── CNAME ├── index.md ├── blog │ └── index.md ├── images │ ├── hn.png │ ├── data.png │ ├── mvvm.png │ ├── state.png │ ├── components.png │ ├── lifecycle.png │ ├── vue-component.png │ └── vue-component-with-pre-processors.png ├── examples │ ├── elastic-header.md │ ├── index.md │ ├── modal.md │ ├── tree-view.md │ ├── grid-component.md │ ├── svg.md │ ├── select2.md │ ├── commits.md │ ├── todomvc.md │ ├── hackernews.md │ └── firebase.md ├── perf │ └── index.md ├── _posts │ ├── vue-011-release.md │ ├── vue-next.md │ ├── 011-component.md │ ├── why-no-template-url.md │ ├── vue-cli.md │ ├── common-gotchas.md │ ├── 1.0.0-release.md │ ├── vuejs-010-release.md │ ├── march-update.md │ ├── announcing-2.0.md │ └── 012-release.md ├── guide │ ├── join.md │ ├── plugins.md │ ├── custom-filter.md │ ├── mixins.md │ ├── conditional.md │ ├── index.md │ ├── events.md │ ├── installation.md │ ├── computed.md │ ├── class-and-style.md │ ├── instance.md │ ├── reactivity.md │ └── comparison.md └── support-vuejs │ └── index.md ├── assets ├── logo.ai ├── state.ai ├── icons.psd └── lifecycle.ai ├── themes └── vue │ ├── _config.yml │ ├── source │ ├── images │ │ ├── check.png │ │ ├── down.png │ │ ├── feed.png │ │ ├── icons.png │ │ ├── juejin.png │ │ ├── logo.png │ │ ├── menu.png │ │ ├── paypal.png │ │ ├── search.png │ │ ├── chaitin.png │ │ ├── itunescn.png │ │ ├── jsfiddle.png │ │ ├── laravel.png │ │ ├── patreon.png │ │ ├── someline.png │ │ ├── htmlburger.png │ │ └── strikingly.png │ ├── css │ │ ├── _settings.styl │ │ ├── _blog.styl │ │ ├── benchmark.styl │ │ ├── _demo.styl │ │ ├── _search.styl │ │ ├── _syntax.styl │ │ ├── _common.styl │ │ ├── page.styl │ │ └── index.styl │ └── js │ │ ├── smooth-scroll.min.js │ │ └── common.js │ └── layout │ ├── partials │ ├── header.ejs │ ├── ad.ejs │ ├── ga.ejs │ ├── community_dropdown.ejs │ ├── main_menu.ejs │ ├── blog.ejs │ ├── sponsors.ejs │ └── sidebar.ejs │ ├── post.ejs │ ├── page.ejs │ ├── layout.ejs │ └── index.ejs ├── .gitignore ├── todomvc ├── package.json ├── js │ ├── store.js │ ├── routes.js │ └── app.js ├── readme.md ├── index.html └── node_modules │ └── todomvc-app-css │ └── index.css ├── README.md ├── package.json ├── Makefile ├── update.js ├── LICENSE └── _config.yml /src/CNAME: -------------------------------------------------------------------------------- 1 | docs.vuejs.id 2 | -------------------------------------------------------------------------------- /src/index.md: -------------------------------------------------------------------------------- 1 | index: true 2 | --- 3 | -------------------------------------------------------------------------------- /src/blog/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | blog_index: true 3 | --- 4 | -------------------------------------------------------------------------------- /assets/logo.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/assets/logo.ai -------------------------------------------------------------------------------- /assets/state.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/assets/state.ai -------------------------------------------------------------------------------- /assets/icons.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/assets/icons.psd -------------------------------------------------------------------------------- /src/images/hn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/src/images/hn.png -------------------------------------------------------------------------------- /assets/lifecycle.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/assets/lifecycle.ai -------------------------------------------------------------------------------- /src/images/data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/src/images/data.png -------------------------------------------------------------------------------- /src/images/mvvm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/src/images/mvvm.png -------------------------------------------------------------------------------- /src/images/state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/src/images/state.png -------------------------------------------------------------------------------- /src/images/components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/src/images/components.png -------------------------------------------------------------------------------- /src/images/lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/src/images/lifecycle.png -------------------------------------------------------------------------------- /src/images/vue-component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/src/images/vue-component.png -------------------------------------------------------------------------------- /themes/vue/_config.yml: -------------------------------------------------------------------------------- 1 | google_analytics: UA-82114244-2 2 | root_domain: docs.vuejs.id 3 | vue_version: 1.0.26 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | db.json 4 | *.log 5 | node_modules/ 6 | public/ 7 | .deploy*/ 8 | src/_drafts 9 | -------------------------------------------------------------------------------- /themes/vue/source/images/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/check.png -------------------------------------------------------------------------------- /themes/vue/source/images/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/down.png -------------------------------------------------------------------------------- /themes/vue/source/images/feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/feed.png -------------------------------------------------------------------------------- /themes/vue/source/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/icons.png -------------------------------------------------------------------------------- /themes/vue/source/images/juejin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/juejin.png -------------------------------------------------------------------------------- /themes/vue/source/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/logo.png -------------------------------------------------------------------------------- /themes/vue/source/images/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/menu.png -------------------------------------------------------------------------------- /themes/vue/source/images/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/paypal.png -------------------------------------------------------------------------------- /themes/vue/source/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/search.png -------------------------------------------------------------------------------- /themes/vue/source/images/chaitin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/chaitin.png -------------------------------------------------------------------------------- /themes/vue/source/images/itunescn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/itunescn.png -------------------------------------------------------------------------------- /themes/vue/source/images/jsfiddle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/jsfiddle.png -------------------------------------------------------------------------------- /themes/vue/source/images/laravel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/laravel.png -------------------------------------------------------------------------------- /themes/vue/source/images/patreon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/patreon.png -------------------------------------------------------------------------------- /themes/vue/source/images/someline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/someline.png -------------------------------------------------------------------------------- /themes/vue/source/images/htmlburger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/htmlburger.png -------------------------------------------------------------------------------- /themes/vue/source/images/strikingly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/themes/vue/source/images/strikingly.png -------------------------------------------------------------------------------- /src/images/vue-component-with-pre-processors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vuejs-id/docs-old/HEAD/src/images/vue-component-with-pre-processors.png -------------------------------------------------------------------------------- /todomvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "director": "^1.2.0", 5 | "vue": "^0.12.8", 6 | "todomvc-common": "^1.0.1", 7 | "todomvc-app-css": "^2.0.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /themes/vue/layout/partials/header.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/examples/elastic-header.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Elastic Header 3 | type: examples 4 | order: 7 5 | --- 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/examples/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown Editor 3 | type: examples 4 | order: 0 5 | --- 6 | 7 | > Dead simple Markdown editor. 8 | 9 | 10 | -------------------------------------------------------------------------------- /themes/vue/layout/partials/ad.ejs: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /src/examples/modal.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Modal Component 3 | type: examples 4 | order: 6 5 | --- 6 | 7 | > Features used: component, prop passing, content insertion, transitions. 8 | 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docs.vuejs.id 2 | 3 | Situs ini dibangun dengan [hexo](http://hexo.io/). Konten situs ditulis menggunakan format Markdown yang bertempat di folder `src`. Pull request dipersilakan! 4 | 5 | ## Pengembangan 6 | 7 | Memulai server pengembangan pada `localhost:4000`: 8 | 9 | ``` 10 | $ npm install -g hexo-cli 11 | $ npm install 12 | $ hexo server 13 | ``` 14 | -------------------------------------------------------------------------------- /src/examples/tree-view.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tree View 3 | type: examples 4 | order: 4 5 | --- 6 | 7 | > Example of a simple tree view implementation showcasing recursive usage of components. 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/examples/grid-component.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Grid Component 3 | type: examples 4 | order: 3 5 | --- 6 | 7 | > This is an example of creating a reusable grid component and using it with external data. 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/examples/svg.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: SVG Graph 3 | type: examples 4 | order: 5 5 | --- 6 | 7 | > This example showcases a combination of custom component, computed property, two-way binding and SVG support. 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/examples/select2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Directive 3 | type: examples 4 | order: 8 5 | --- 6 | 7 | > In this example we are integrating a 3rd party jQuery plugin (select2) by wrapping it inside a custom directive. 8 | 9 | 10 | -------------------------------------------------------------------------------- /todomvc/js/store.js: -------------------------------------------------------------------------------- 1 | /*jshint unused:false */ 2 | 3 | (function (exports) { 4 | 5 | 'use strict'; 6 | 7 | var STORAGE_KEY = 'todos-vuejs'; 8 | 9 | exports.todoStorage = { 10 | fetch: function () { 11 | return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]'); 12 | }, 13 | save: function (todos) { 14 | localStorage.setItem(STORAGE_KEY, JSON.stringify(todos)); 15 | } 16 | }; 17 | 18 | })(window); 19 | -------------------------------------------------------------------------------- /src/examples/commits.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: GitHub Commits 3 | type: examples 4 | order: 1 5 | --- 6 | 7 | > This example fetches latest Vue.js commits data from GitHub's API and displays them as a list. You can switch between the master and dev branches. 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/examples/todomvc.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: TodoMVC 3 | type: examples 4 | order: 9 5 | --- 6 | 7 | > This is a fully spec-compliant TodoMVC implementation in under 120 effective lines of JavaScript (excluding comments and blank lines). 8 | 9 | 10 | 11 | > [[Source](https://github.com/vuejs/vue/tree/dev/examples/todomvc)] 12 | -------------------------------------------------------------------------------- /src/examples/hackernews.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: HackerNews Clone 3 | type: examples 4 | order: 10 5 | --- 6 | 7 | > This is a HackerNews clone built upon HN's official Firebase API, and using Webpack + vue-loader for the build setup. 8 | 9 |
10 | 11 |
12 | 13 | > [[Source](https://github.com/vuejs/vue-hackernews)] 14 | -------------------------------------------------------------------------------- /themes/vue/layout/partials/ga.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /todomvc/js/routes.js: -------------------------------------------------------------------------------- 1 | /*global app, Router */ 2 | 3 | (function (app, Router) { 4 | 5 | 'use strict'; 6 | 7 | var router = new Router(); 8 | 9 | ['all', 'active', 'completed'].forEach(function (visibility) { 10 | router.on(visibility, function () { 11 | app.visibility = visibility; 12 | }); 13 | }); 14 | 15 | router.configure({ 16 | notfound: function () { 17 | window.location.hash = ''; 18 | app.visibility = 'all'; 19 | } 20 | }); 21 | 22 | router.init(); 23 | 24 | })(app, Router); 25 | -------------------------------------------------------------------------------- /themes/vue/source/css/_settings.styl: -------------------------------------------------------------------------------- 1 | // font faces 2 | $body-font = 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif 3 | $logo-font = 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif 4 | $code-font = 'Roboto Mono', Monaco, courier, monospace 5 | 6 | // font sizes 7 | $body-font-size = 15px 8 | $code-font-size = .8em 9 | 10 | // colors 11 | $dark = #2c3e50 12 | $medium = #34495e 13 | $light = #7f8c8d 14 | $green = #42b983 15 | $border = #dddddd 16 | $codebg = #f8f8f8 17 | $red = #ff6666 18 | 19 | $radius = 2px 20 | -------------------------------------------------------------------------------- /src/examples/firebase.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Firebase + Validation 3 | type: examples 4 | order: 2 5 | --- 6 | 7 | > This example uses [Firebase](https://www.firebase.com/) as the data persistence backend and syncs between clients in real time (you can try opening it in multiple browser tabs). In addition, it performs instant validation using computed properties and triggers CSS transitions when adding/removing items. 8 | 9 | 10 | -------------------------------------------------------------------------------- /themes/vue/layout/partials/community_dropdown.ejs: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuejs.org", 3 | "version": "1.0.18", 4 | "private": true, 5 | "hexo": { 6 | "version": "3.2.2" 7 | }, 8 | "dependencies": { 9 | "hexo": "^3.2.0", 10 | "hexo-deployer-git": "0.1.0", 11 | "hexo-generator-archive": "^0.1.4", 12 | "hexo-generator-category": "^0.1.3", 13 | "hexo-generator-feed": "^1.1.0", 14 | "hexo-generator-index": "^0.2.0", 15 | "hexo-generator-tag": "^0.2.0", 16 | "hexo-renderer-ejs": "^0.2.0", 17 | "hexo-renderer-marked": "^0.2.10", 18 | "hexo-renderer-stylus": "^0.3.1", 19 | "hexo-server": "^0.2.0" 20 | } 21 | } -------------------------------------------------------------------------------- /themes/vue/source/css/_blog.styl: -------------------------------------------------------------------------------- 1 | .content.blog 2 | h1 3 | margin 0 0 .5em 4 | h2 5 | margin .8em 0 6 | padding-bottom 0 7 | border-bottom none 8 | a 9 | color $dark 10 | &:hover 11 | border-bottom 2px solid $green 12 | h4 13 | color $light 14 | margin 1.2em 0 15 | figure, p 16 | margin-left 0 17 | .post 18 | padding 1em 0 2em 19 | border-bottom 1px solid $border 20 | 21 | @media screen and (max-width: 1400px) and (min-width: 720px) 22 | .content.blog.post 23 | margin 0 0 0 280px 24 | -------------------------------------------------------------------------------- /themes/vue/layout/partials/main_menu.ejs: -------------------------------------------------------------------------------- 1 |
  • 2 |
    3 | 4 |
    5 |
  • 6 |
  • Guide
  • 7 |
  • API
  • 8 |
  • Examples
  • 9 |
  • Blog
  • 10 | <%- partial('partials/community_dropdown') %> 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: update deploy 2 | 3 | deploy: 4 | rm -f db.json 5 | hexo generate 6 | cp -R ./todomvc public/examples 7 | mkdir -p public/unit 8 | cp -R ../vue/test/unit/lib/ public/unit/lib 9 | cp ../vue/test/unit/index.html public/unit/index.html 10 | cp ../vue/test/unit/specs.js public/unit/specs.js 11 | cp ../vue/test/unit/specs.js.map public/unit/specs.js.map 12 | hexo deploy 13 | 14 | update: 15 | cd ../vue && \ 16 | git checkout -- dist && \ 17 | git checkout master && \ 18 | npm run build && \ 19 | npm run build-test > /dev/null 20 | cp ../vue/dist/vue.min.js themes/vue/source/js/vue.min.js 21 | cp ../vue/dist/vue.js themes/vue/source/js/vue.js 22 | node update.js 23 | -------------------------------------------------------------------------------- /themes/vue/source/css/benchmark.styl: -------------------------------------------------------------------------------- 1 | #benchmark-results 2 | margin-bottom 2em 3 | ul 4 | list-style-type none 5 | padding 0 6 | margin-left 0 7 | 8 | .framework, .time, .bar, .inner 9 | display inline-block 10 | 11 | .framework 12 | width 4.2em 13 | //text-align right 14 | margin-right 1em 15 | font-weight 600 16 | 17 | .time 18 | width 4.2em 19 | margin-right 1em 20 | 21 | .bar 22 | width 60% 23 | &.min .inner 24 | background-color #e74c3c 25 | 26 | .inner 27 | height 3px 28 | vertical-align middle 29 | background-color #3498db 30 | 31 | @media screen and (max-width: 600px) 32 | #benchmark-results 33 | .bar 34 | width 45% -------------------------------------------------------------------------------- /themes/vue/layout/partials/blog.ejs: -------------------------------------------------------------------------------- 1 | 6 |
    7 |

    The Vue.js Blog

    8 |

    9 | 10 | 11 | 12 |

    13 | <% site.posts.sort('date', -1).each(function (post) { %> 14 |
    15 |

    <%- post.title %>

    16 |

    <%- post.date.format('MMM D[,] YYYY') %>

    17 |
    <%- post.excerpt %>
    18 | ... continue reading 19 |
    20 | <% }) %> 21 |
    22 | -------------------------------------------------------------------------------- /themes/vue/source/css/_demo.styl: -------------------------------------------------------------------------------- 1 | #demo, .demo 2 | border 1px solid #eee 3 | border-radius $radius 4 | padding 25px 35px 5 | margin-bottom 40px 6 | font-size 1.2em 7 | line-height 1.5em 8 | -webkit-user-select: none; 9 | -moz-user-select: none; 10 | -ms-user-select: none; 11 | user-select: none; 12 | h1 13 | margin 0 0 .5em 14 | font-size 1.8em 15 | ul 16 | padding-left 1.5em 17 | margin 0 18 | li 19 | cursor pointer 20 | color $medium 21 | -ms-user-select none 22 | -moz-user-select none 23 | -webkit-user-select none 24 | &.done 25 | color $light 26 | text-decoration line-through 27 | 28 | ul#demo, ul.demo 29 | li 30 | margin-left 1.5em 31 | 32 | @media screen and (max-width: 720px) 33 | #demo, .demo 34 | margin-left 0 35 | -------------------------------------------------------------------------------- /update.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var version = require('../vue/package.json').version 3 | var themeconfPath = 'themes/vue/_config.yml' 4 | var installPath = 'src/guide/installation.md' 5 | var themeconfig = fs.readFileSync(themeconfPath, 'utf-8') 6 | var installation = fs.readFileSync(installPath, 'utf-8') 7 | 8 | fs.writeFileSync( 9 | themeconfPath, 10 | themeconfig.replace(/vue_version: .*/, 'vue_version: ' + version) 11 | ) 12 | 13 | var sizes = { 14 | dev: 'vue.js', 15 | min: 'vue.min.js', 16 | gz: 'vue.min.js.gz' 17 | } 18 | 19 | for (var file in sizes) { 20 | var filesize = fs.statSync('../vue/dist/' + sizes[file], 'utf-8').size 21 | sizes[file] = (filesize / 1024).toFixed(2) 22 | } 23 | 24 | fs.writeFileSync( 25 | installPath, 26 | installation 27 | .replace(/vue_version: .*/, 'vue_version: ' + version) 28 | .replace(/(\w+)_size:.*/g, function (m, p1) { 29 | return p1 + '_size: "' + sizes[p1] + '"' 30 | }) 31 | ) 32 | -------------------------------------------------------------------------------- /themes/vue/source/css/_search.styl: -------------------------------------------------------------------------------- 1 | @import '_settings' 2 | 3 | $border = #ddd 4 | 5 | .algolia-autocomplete 6 | line-height normal 7 | 8 | .aa-dropdown-menu 9 | border-color #999 10 | font-size 0.9rem 11 | 12 | @media (min-width: 768px) 13 | .aa-dropdown-menu 14 | min-width: 515px 15 | 16 | .algolia-docsearch-suggestion 17 | border-color $border 18 | 19 | .algolia-docsearch-suggestion--content 20 | color $dark 21 | 22 | .algolia-docsearch-suggestion--subcategory-column 23 | border-color $border 24 | 25 | .algolia-docsearch-suggestion--category-header 26 | background: $green 27 | 28 | .algolia-docsearch-footer 29 | border-color $border 30 | 31 | .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight 32 | background rgba(255, 255, 255, 0.6) 33 | 34 | .algolia-docsearch-suggestion--highlight 35 | color: #2c815b 36 | 37 | .aa-cursor .algolia-docsearch-suggestion--content 38 | color: $dark 39 | -------------------------------------------------------------------------------- /src/perf/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Performance Comparisons 3 | --- 4 | 5 | ## TodoMVC Benchmark 6 | 7 | > *Last Updated: 2014-10-12* 8 | 9 | Looking for the TodoMVC Benchmark? It's been removed because after discussion with some other framework authors we have agreed that: 10 | 11 | 1. The original intention of these benchmarks were for comparing Browser performance rather than that of frameworks. The "synchrorously trigger an action xxx times" test routine doesn't reflect meaningful real world user actions. 12 | 13 | 2. Due to internal implementation differences, frameworks that uses async rendering (e.g. Vue, Om, Mercury) gains the advantage by skipping part of the calculations that happened in the same event loop. The real world user experience doesn't demonstrate such dramatic difference. 14 | 15 | 3. Overall this benchmark suite gave rise to more controversy than constructive insights, so it's been removed and I'd be happy to replace it with a more meaningful way to measure front-end performance. 16 | -------------------------------------------------------------------------------- /themes/vue/layout/post.ejs: -------------------------------------------------------------------------------- 1 | 21 |
    22 | <%- partial('partials/ad') %> 23 |

    <%- page.title %>

    24 |

    <%- page.date.format('MMM D[,] YYYY') %>

    25 | <%- page.content %> 26 |
    27 | -------------------------------------------------------------------------------- /src/_posts/vue-011-release.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vue.js 0.11 released! 3 | date: 2014-11-09 09:23:40 4 | --- 5 | 6 | After the long wait, [Vue.js 0.11 **Cowboy Bebop**](https://github.com/yyx990803/vue/releases/tag/0.11.0) is finally here! Thanks to everyone who tried out the release candidate versions and provided feedback / bug reports along the way. 7 | 8 | 9 | 10 | The 0.11 release introduced many new features and also a fair number of breaking changes, so please carefully read through the [0.11 Change List](https://github.com/yyx990803/vue/blob/master/changes.md) before upgrading. Aside from the API changes, 0.11 also ships with better [code quality](https://codeclimate.com/github/yyx990803/vue) and [test coverage](https://coveralls.io/r/yyx990803/vue), and is considerably more robust in almost every aspect. 11 | 12 | This documentation site has been fully upgraded to match the new 0.11 API. For the now legacy 0.10.6 version, you can still find documentations for it at [legacy.vuejs.org](http://legacy.vuejs.org). 13 | -------------------------------------------------------------------------------- /todomvc/readme.md: -------------------------------------------------------------------------------- 1 | # Vue.js TodoMVC Example 2 | 3 | > Vue.js is a library for building interactive web interfaces. 4 | It provides data-driven, nestable view components with a simple and flexible API. 5 | 6 | > _[Vue.js - vuejs.org](http://vuejs.org)_ 7 | 8 | ## Learning Vue.js 9 | The [Vue.js website](http://vuejs.org/) is a great resource to get started. 10 | 11 | Here are some links you may find helpful: 12 | 13 | * [Official Guide](http://vuejs.org/guide/) 14 | * [API Reference](http://vuejs.org/api/) 15 | * [Examples](http://vuejs.org/examples/) 16 | * [Building Larger Apps with Vue.js](http://vuejs.org/guide/application.html) 17 | 18 | Get help from other Vue.js users: 19 | 20 | * [Vue.js on Twitter](https://twitter.com/vuejs) 21 | * [Vue.js on Gitter](https://gitter.im/vuejs/vue) 22 | * [Vue.js discussion repo](https://github.com/vuejs/Discussion/issues) 23 | 24 | _If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._ 25 | 26 | ## Credit 27 | 28 | This TodoMVC application was created by [Evan You](http://evanyou.me). 29 | -------------------------------------------------------------------------------- /themes/vue/layout/partials/sponsors.ejs: -------------------------------------------------------------------------------- 1 | 2 | Disponsori oleh 3 |
    4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2015 Yuxi Evan You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /themes/vue/layout/partials/sidebar.ejs: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /themes/vue/layout/page.ejs: -------------------------------------------------------------------------------- 1 | <% if (page.type) { %> 2 | <%- partial('partials/sidebar', { type: page.type, index: page.index }) %> 3 | <% } %> 4 |
    5 | <%- partial('partials/ad') %> 6 |

    <%- page.title %><%- page.type === 'examples' ? ' Example' : '' %>

    7 | <%- page.content %> 8 | <% if (page.type === 'guide') { %> 9 | 17 | <% } %> 18 | 25 |
    26 | -------------------------------------------------------------------------------- /themes/vue/source/css/_syntax.styl: -------------------------------------------------------------------------------- 1 | .gutter pre 2 | color #999 3 | 4 | pre 5 | color: #525252 6 | .function .keyword, 7 | .constant 8 | color: #0092db 9 | .keyword, 10 | .attribute 11 | color: #e96900 12 | .number, 13 | .literal 14 | color: #AE81FF 15 | .tag, 16 | .tag .title, 17 | .change, 18 | .winutils, 19 | .flow, 20 | .lisp .title, 21 | .clojure .built_in, 22 | .nginx .title, 23 | .tex .special 24 | color: #2973b7 25 | .class .title 26 | color: white 27 | .symbol, 28 | .symbol .string, 29 | .value, 30 | .regexp 31 | color: $green 32 | .title 33 | color: #A6E22E 34 | .tag .value, 35 | .string, 36 | .subst, 37 | .haskell .type, 38 | .preprocessor, 39 | .ruby .class .parent, 40 | .built_in, 41 | .sql .aggregate, 42 | .django .template_tag, 43 | .django .variable, 44 | .smalltalk .class, 45 | .javadoc, 46 | .django .filter .argument, 47 | .smalltalk .localvars, 48 | .smalltalk .array, 49 | .attr_selector, 50 | .pseudo, 51 | .addition, 52 | .stream, 53 | .envvar, 54 | .apache .tag, 55 | .apache .cbracket, 56 | .tex .command, 57 | .prompt 58 | color: $green 59 | .comment, 60 | .java .annotation, 61 | .python .decorator, 62 | .template_comment, 63 | .pi, 64 | .doctype, 65 | .deletion, 66 | .shebang, 67 | .apache .sqbracket, 68 | .tex .formula 69 | color: #b3b3b3 70 | .coffeescript .javascript, 71 | .javascript .xml, 72 | .tex .formula, 73 | .xml .javascript, 74 | .xml .vbscript, 75 | .xml .css, 76 | .xml .cdata 77 | opacity: 0.5 -------------------------------------------------------------------------------- /src/_posts/vue-next.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vue.js 0.10.6, and what's next 3 | date: 2014-07-29 00:04:55 4 | --- 5 | 6 | ## 0.10.6 7 | 8 | Vue.js 0.10.6 has been released! This is another small bug-fix release and will be the last maintainance version before the next major release. 9 | 10 | 11 | 12 | - fix `v-style` error when value is falsy or a number. ( thanks to [@dmfilipenko](https://github.com/dmfilipenko) ) 13 | - fix the built-in `currency` filter error when value is a string ( thanks to [@dmfilipenko](https://github.com/dmfilipenko) ) 14 | - fix `Vue.require` for building with Component v1.0+ ( thanks to [@kewah](https://github.com/kewah) ) 15 | - Allow template nodes to be passed as a template option ( thanks to [@jordangarcia](https://github.com/jordangarcia) ) 16 | - `vm.$destroy()` now accepts an optional argument `noRemove`. When passed in as `true` it will leave the vm's DOM node intact after the vm is destroyed. 17 | 18 | ## Vue-next 19 | 20 | Some of you might have noticed there is a [next](https://github.com/yyx990803/vue/tree/next) branch in the repo. And yes, I am re-writing Vue.js from scratch. There are two main reasons: 21 | 22 | - Fix some issues that are caused by design flaws in the current version. Because these changes affect the design of some core modules, it is actually easier to rewrite than to apply on the current codebase. 23 | - Improve general code quality (in particular, `compiler.js` as of now is a big pile of mess, and comments are not consistent across the codebase.) 24 | 25 | Take note that the `next` branch is still in **very** early stage. The internals will change a lot, and when it comes out it **will** break current applications. Despite that I will try to keep the API changes to a minimum. Major differences with current 0.10 branch are documented in [`changes.md`](https://github.com/yyx990803/vue/blob/next/changes.md). The list is obviously incomplete and subject to change, some of them are simply ideas, but it at least gives you a taste of what to expect, and I'd appreicate your feedback on any of the topics. 26 | 27 | Share your thoughts at [vuejs/Discussion](https://github.com/vuejs/Discussion/issues). 28 | -------------------------------------------------------------------------------- /themes/vue/layout/layout.ejs: -------------------------------------------------------------------------------- 1 | <% var isIndex = page.path === 'index.html' %> 2 | 3 | 4 | 5 | <%- page.title ? page.title + ' - ' : '' %>vue.js 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | <%- css(isIndex ? 'css/index' : 'css/page') %> 17 | <%- partial('partials/ga') %> 18 | 19 | 20 | 21 |
    22 | 23 | 24 |
    25 | <% if (!isIndex) { %> 26 | <%- partial('partials/header') %> 27 |
    28 | <% if (page.blog_index) { %> 29 | <%- partial('partials/blog') %> 30 | <% } else { %> 31 | <%- body %> 32 | <% } %> 33 |
    34 | 35 | 36 | 37 | <% } else { %> 38 | <%- body %> 39 | <% } %> 40 | 41 | 42 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/guide/join.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Join the Vue Community! 3 | type: guide 4 | order: 20 5 | --- 6 | 7 | ## Join the Vue.js Community! 8 | 9 | The vibrant community around Vue.js is continually growing. Nevertheless, helpful hands are always welcome. In fact, a growing community is the best sign of a healthy OSS project worth putting any effort into, even if it is as the user of the software. 10 | 11 | If you would like to also be a part of the Vue.js community, this page was meant to support your endeavors. Have a look at the resources listed below to get some orientation around the sailing ship of Vue.js and... 12 | 13 | ....welcome aboard! 14 | 15 | ## Resources You Should Know About! 16 | 17 | ### The Community 18 | - [The Forum](http://forum.vuejs.org/) - THE best place to ask questions and get answers about Vue.js and its components. 19 | - [Gitter Channel](https://gitter.im/vuejs/vue) - A place for devs to meet and chat. You can ask questions here, but the forum is the better platform, since the discussions are threaded. 20 | - [Github](https://github.com/vuejs) - Report bugs or fork repositories to offer pull requests. Any contribution is greatly appreciated! 21 | 22 | 23 | ### Third Party Contributions 24 | 25 | - [The Awesome Vue Page](https://github.com/vuejs/awesome-vue) - See what other awesome resources have been published by other awesome people. 26 | - [The "Show and Tell" Subforum](http://forum.vuejs.org/category/15/show-tell) - Another great place to check out what others have built with and for the growing Vue ecosystem. 27 | 28 | ### Contributing to Vue 29 | 30 | - [The rules to contribute](https://github.com/vuejs/vue/blob/dev/CONTRIBUTING.md) - As with any community, there has to be rules, in order to ensure everyone is doing the right things the right way. 31 | 32 | - The Main Components of Vue 33 | - [Vue](https://github.com/vuejs/vue) - The core repository. 34 | - [Vuex](https://github.com/vuejs/vuex) - A Flux-inspired Application Architecture for Vue.js. 35 | - [Vue-router](https://github.com/vuejs/vue-router) - A routing system for SPAs with Vue.js. 36 | - [Vue-resource](https://github.com/vuejs/vue-resource) - A plugin, which provides services for making web requests and to handle responses using XMLHttpRequests or JSONP. 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /todomvc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vue.js • TodoMVC 6 | 7 | 8 | 9 | 10 |
    11 |
    12 |

    todos

    13 | 18 |
    19 |
    20 | 21 | 38 |
    39 | 52 |
    53 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/support-vuejs/index.md: -------------------------------------------------------------------------------- 1 | # Support Vue.js Development 2 | 3 | 4 | 5 | Support Vue.js on Patreon (recurring pledge) 6 | 7 | 8 | 9 | 10 | Donate via PayPal (one time) 11 | 12 | 13 | ## Current premium sponsors: 14 | 15 |

    16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |

    41 | 42 | Vue.js is an MIT licensed open source project and completely free to use. 43 | However, the amount of effort needed to maintain and develop new features for the project is not sustainable without proper financial backing. You can support Vue.js development by [pledging on Patreon](https://www.patreon.com/evanyou) or [donating on PayPal](https://www.paypal.me/evanyou). 44 | 45 | If you run a business and are using Vue in a revenue-generating product, it makes business sense to sponsor Vue development: **it ensures the project that your product relies on stays healthy and actively maintained.** It can also help your exposure in the Vue community and makes it easier to attract Vue developers. 46 | 47 | If you are an individual user and have enjoyed the productivity of using Vue, consider donating as a sign of appreciation - like buying me coffee once in a while :) 48 | 49 | As of now I am exploring the possibility of working on Vue.js fulltime - if you are a business that is building core products using Vue.js, I am also open to conversations regarding custom sponsorship / consulting arrangements. [Get in touch on Twitter](https://twitter.com/youyuxi). 50 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Hexo Configuration 2 | ## Docs: http://zespia.tw/hexo/docs/configuration.html 3 | ## Source: https://github.com/tommy351/hexo/ 4 | 5 | # Site 6 | title: Vue.js Indonesia - Documentation 7 | subtitle: 8 | description: "Reactive Components for Modern Web Interfaces" 9 | author: Evan You 10 | email: 11 | language: 12 | 13 | # URL 14 | ## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/' 15 | url: http://docs.vuejs.id 16 | root: / 17 | permalink: :year/:month/:day/:title/ 18 | tag_dir: tags 19 | archive_dir: archives 20 | category_dir: categories 21 | code_dir: downloads/code 22 | 23 | # Directory 24 | source_dir: src 25 | public_dir: public 26 | 27 | # Writing 28 | new_post_name: :title.md # File name of new posts 29 | default_layout: post 30 | auto_spacing: false # Add spaces between asian characters and western characters 31 | titlecase: false # Transform title into titlecase 32 | external_link: true # Open external links in new tab 33 | max_open_file: 100 34 | multi_thread: true 35 | filename_case: 0 36 | render_drafts: false 37 | post_asset_folder: false 38 | highlight: 39 | enable: true 40 | line_number: false 41 | tab_replace: 42 | 43 | # Category & Tag 44 | default_category: uncategorized 45 | category_map: 46 | tag_map: 47 | 48 | # Archives 49 | ## 2: Enable pagination 50 | ## 1: Disable pagination 51 | ## 0: Fully Disable 52 | archive: 0 53 | category: 0 54 | tag: 0 55 | 56 | # Server 57 | ## Hexo uses Connect as a server 58 | ## You can customize the logger format as defined in 59 | ## http://www.senchalabs.org/connect/logger.html 60 | port: 4000 61 | logger: false 62 | logger_format: 63 | 64 | # Date / Time format 65 | ## Hexo uses Moment.js to parse and display date 66 | ## You can customize the date format as defined in 67 | ## http://momentjs.com/docs/#/displaying/format/ 68 | date_format: MMM D YYYY 69 | time_format: H:mm:ss 70 | 71 | # Pagination 72 | ## Set per_page to 0 to disable pagination 73 | per_page: 10 74 | pagination_dir: page 75 | 76 | # Disqus 77 | disqus_shortname: 78 | 79 | # Extensions 80 | ## Plugins: https://github.com/tommy351/hexo/wiki/Plugins 81 | ## Themes: https://github.com/tommy351/hexo/wiki/Themes 82 | theme: vue 83 | exclude_generator: 84 | 85 | # Markdown 86 | ## https://github.com/chjj/marked 87 | markdown: 88 | gfm: true 89 | pedantic: false 90 | sanitize: false 91 | tables: true 92 | breaks: true 93 | smartLists: true 94 | smartypants: true 95 | 96 | # Deployment 97 | ## Docs: http://zespia.tw/hexo/docs/deployment.html 98 | deploy: 99 | type: git 100 | repository: git@github.com:vuejs-id/docs.git 101 | 102 | feed: 103 | type: atom 104 | path: atom.xml 105 | limit: 20 106 | -------------------------------------------------------------------------------- /src/guide/plugins.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Plugins 3 | type: guide 4 | order: 17 5 | --- 6 | 7 | 8 | 9 | ## Writing a Plugin 10 | 11 | Plugins usually add global-level functionality to Vue. There is no strictly defined scope for a plugin - there are typically several types of plugins you can write: 12 | 13 | 1. Add some global methods or properties. e.g. [vue-element](https://github.com/vuejs/vue-element) 14 | 15 | 2. Add one or more global assets: directives/filters/transitions etc. e.g. [vue-touch](https://github.com/vuejs/vue-touch) 16 | 17 | 3. Add some Vue instance methods by attaching them to Vue.prototype. 18 | 19 | 4. A library that provides an API of its own, while at the same time injecting some combination of the above. e.g. [vue-router](https://github.com/vuejs/vue-router) 20 | 21 | A Vue.js plugin should expose an `install` method. The method will be called with the `Vue` constructor as the first argument, along with possible options: 22 | 23 | ``` js 24 | MyPlugin.install = function (Vue, options) { 25 | // 1. add global method or property 26 | Vue.myGlobalMethod = ... 27 | // 2. add a global asset 28 | Vue.directive('my-directive', {}) 29 | // 3. add an instance method 30 | Vue.prototype.$myMethod = ... 31 | } 32 | ``` 33 | 34 | ## Using a Plugin 35 | 36 | Use plugins by calling the `Vue.use()` global method: 37 | 38 | ``` js 39 | // calls `MyPlugin.install(Vue)` 40 | Vue.use(MyPlugin) 41 | ``` 42 | 43 | You can optionally pass in some options: 44 | 45 | ``` js 46 | Vue.use(MyPlugin, { someOption: true }) 47 | ``` 48 | 49 | Some plugins such as `vue-router` automatically calls `Vue.use()` if `Vue` is available as a global variable. However in a module environment you always need to call `Vue.use()` explicitly: 50 | 51 | ``` js 52 | // When using CommonJS via Browserify or Webpack 53 | var Vue = require('vue') 54 | var VueRouter = require('vue-router') 55 | 56 | // Don't forget to call this 57 | Vue.use(VueRouter) 58 | ``` 59 | 60 | ## Existing Plugins & Tools 61 | 62 | - [vue-router](https://github.com/vuejs/vue-router): The official router for Vue.js. Deeply integrated with Vue.js core to make building Single Page Applications a breeze. 63 | 64 | - [vue-resource](https://github.com/vuejs/vue-resource): A plugin that provides services for making web requests and handle responses using a XMLHttpRequest or JSONP. 65 | 66 | - [vue-async-data](https://github.com/vuejs/vue-async-data): Async data loading plugin. 67 | 68 | - [vue-validator](https://github.com/vuejs/vue-validator): A plugin for form validations. 69 | 70 | - [vue-devtools](https://github.com/vuejs/vue-devtools): A Chrome devtools extension for debugging Vue.js applications. 71 | 72 | - [vue-touch](https://github.com/vuejs/vue-touch): Add touch-gesture directives using Hammer.js. 73 | 74 | - [vue-element](https://github.com/vuejs/vue-element): Register Custom Elements with Vue.js. 75 | 76 | - [vue-animated-list](https://github.com/vuejs/vue-animated-list): A plugin for easily animating `v-for` rendered lists. 77 | 78 | - [List of User Contributed Tools](https://github.com/vuejs/awesome-vue#libraries--plugins) 79 | -------------------------------------------------------------------------------- /todomvc/js/app.js: -------------------------------------------------------------------------------- 1 | /*global Vue, todoStorage */ 2 | 3 | (function (exports) { 4 | 5 | 'use strict'; 6 | 7 | var filters = { 8 | all: function (todos) { 9 | return todos; 10 | }, 11 | active: function (todos) { 12 | return todos.filter(function (todo) { 13 | return !todo.completed; 14 | }); 15 | }, 16 | completed: function (todos) { 17 | return todos.filter(function (todo) { 18 | return todo.completed; 19 | }); 20 | } 21 | }; 22 | 23 | exports.app = new Vue({ 24 | 25 | // the root element that will be compiled 26 | el: '.todoapp', 27 | 28 | // app initial state 29 | data: { 30 | todos: todoStorage.fetch(), 31 | newTodo: '', 32 | editedTodo: null, 33 | visibility: 'all' 34 | }, 35 | 36 | // watch todos change for localStorage persistence 37 | watch: { 38 | todos: { 39 | handler: function (todos) { 40 | todoStorage.save(todos); 41 | }, 42 | deep: true 43 | } 44 | }, 45 | 46 | // computed properties 47 | // http://vuejs.org/guide/computed.html 48 | computed: { 49 | filteredTodos: function () { 50 | return filters[this.visibility](this.todos); 51 | }, 52 | remaining: function () { 53 | return filters.active(this.todos).length; 54 | }, 55 | allDone: { 56 | get: function () { 57 | return this.remaining === 0; 58 | }, 59 | set: function (value) { 60 | this.todos.forEach(function (todo) { 61 | todo.completed = value; 62 | }); 63 | } 64 | } 65 | }, 66 | 67 | // methods that implement data logic. 68 | // note there's no DOM manipulation here at all. 69 | methods: { 70 | 71 | addTodo: function () { 72 | var value = this.newTodo && this.newTodo.trim(); 73 | if (!value) { 74 | return; 75 | } 76 | this.todos.push({ title: value, completed: false }); 77 | this.newTodo = ''; 78 | }, 79 | 80 | removeTodo: function (todo) { 81 | this.todos.$remove(todo); 82 | }, 83 | 84 | editTodo: function (todo) { 85 | this.beforeEditCache = todo.title; 86 | this.editedTodo = todo; 87 | }, 88 | 89 | doneEdit: function (todo) { 90 | if (!this.editedTodo) { 91 | return; 92 | } 93 | this.editedTodo = null; 94 | todo.title = todo.title.trim(); 95 | if (!todo.title) { 96 | this.removeTodo(todo); 97 | } 98 | }, 99 | 100 | cancelEdit: function (todo) { 101 | this.editedTodo = null; 102 | todo.title = this.beforeEditCache; 103 | }, 104 | 105 | removeCompleted: function () { 106 | this.todos = filters.active(this.todos); 107 | } 108 | }, 109 | 110 | // a custom directive to wait for the DOM to be updated 111 | // before focusing on the input field. 112 | // http://vuejs.org/guide/custom-directive.html 113 | directives: { 114 | 'todo-focus': function (value) { 115 | if (!value) { 116 | return; 117 | } 118 | var el = this.el; 119 | Vue.nextTick(function () { 120 | el.focus(); 121 | }); 122 | } 123 | } 124 | }); 125 | 126 | })(window); 127 | -------------------------------------------------------------------------------- /src/guide/custom-filter.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Filters 3 | type: guide 4 | order: 15 5 | --- 6 | 7 | ## Basics 8 | 9 | Similar to custom directives, you can register a custom filter with the global `Vue.filter()` method, passing in a **filterID** and a **filter function**. The filter function takes a value as the argument and returns the transformed value: 10 | 11 | ``` js 12 | Vue.filter('reverse', function (value) { 13 | return value.split('').reverse().join('') 14 | }) 15 | ``` 16 | 17 | ``` html 18 | 19 | 20 | ``` 21 | 22 | The filter function also receives any inline arguments: 23 | 24 | ``` js 25 | Vue.filter('wrap', function (value, begin, end) { 26 | return begin + value + end 27 | }) 28 | ``` 29 | 30 | ``` html 31 | 32 | 33 | ``` 34 | 35 | ## Two-way Filters 36 | 37 | Up till now we have used filters to transform values coming from the model and before displaying them in the view. But it is also possible to define a filter that transforms the value before it is written back to the model from the view (input elements): 38 | 39 | ``` js 40 | Vue.filter('currencyDisplay', { 41 | // model -> view 42 | // formats the value when updating the input element. 43 | read: function(val) { 44 | return '$'+val.toFixed(2) 45 | }, 46 | // view -> model 47 | // formats the value when writing to the data. 48 | write: function(val, oldVal) { 49 | var number = +val.replace(/[^\d.]/g, '') 50 | return isNaN(number) ? 0 : parseFloat(number.toFixed(2)) 51 | } 52 | }) 53 | ``` 54 | 55 | Demo: 56 | 57 | {% raw %} 58 |
    59 | 60 |

    Model value: {{money}}

    61 |
    62 | 81 | {% endraw %} 82 | 83 | ## Dynamic Arguments 84 | 85 | If a filter argument is not enclosed by quotes, it will be evaluated dynamically in the current vm's data context. In addition, the filter function is always invoked using the current vm as its `this` context. For example: 86 | 87 | ``` html 88 | 89 | {{msg | concat userInput}} 90 | ``` 91 | 92 | ``` js 93 | Vue.filter('concat', function (value, input) { 94 | // here `input` === `this.userInput` 95 | return value + input 96 | }) 97 | ``` 98 | 99 | For this simple example above, you can achieve the same result with just an expression, but for more complicated procedures that need more than one statement, you need to put them either in a computed property or a custom filter. 100 | 101 | The built-in `filterBy` and `orderBy` filters are both filters that perform non-trivial work on the Array being passed in and relies on the current state of the owner Vue instance. 102 | -------------------------------------------------------------------------------- /themes/vue/source/js/smooth-scroll.min.js: -------------------------------------------------------------------------------- 1 | /** smooth-scroll v5.1.2, by Chris Ferdinandi | http://github.com/cferdinandi/smooth-scroll | Licensed under MIT: http://gomakethings.com/mit/ */ 2 | !function(t,e){"function"==typeof define&&define.amd?define("smoothScroll",e(t)):"object"==typeof exports?module.exports=e(t):t.smoothScroll=e(t)}(this,function(t){"use strict";var e,n={},o=!!document.querySelector&&!!t.addEventListener,r={speed:500,easing:"easeInOutCubic",offset:0,updateURL:!0,callbackBefore:function(){},callbackAfter:function(){}},a=function(t,e,n){if("[object Object]"===Object.prototype.toString.call(t))for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&e.call(n,t[o],o,t);else for(var r=0,a=t.length;a>r;r++)e.call(n,t[r],r,t)},c=function(t,e){var n={};return a(t,function(e,o){n[o]=t[o]}),a(e,function(t,o){n[o]=e[o]}),n},u=function(t,e){for(var n=e.charAt(0);t&&t!==document;t=t.parentNode)if("."===n){if(t.classList.contains(e.substr(1)))return t}else if("#"===n){if(t.id===e.substr(1))return t}else if("["===n&&t.hasAttribute(e.substr(1,e.length-2)))return t;return!1},i=function(t){for(var e,n=String(t),o=n.length,r=-1,a="",c=n.charCodeAt(0);++r=1&&31>=e||127==e||0===r&&e>=48&&57>=e||1===r&&e>=48&&57>=e&&45===c?"\\"+e.toString(16)+" ":e>=128||45===e||95===e||e>=48&&57>=e||e>=65&&90>=e||e>=97&&122>=e?n.charAt(r):"\\"+n.charAt(r)}return a},s=function(t,e){var n;return"easeInQuad"===t&&(n=e*e),"easeOutQuad"===t&&(n=e*(2-e)),"easeInOutQuad"===t&&(n=.5>e?2*e*e:-1+(4-2*e)*e),"easeInCubic"===t&&(n=e*e*e),"easeOutCubic"===t&&(n=--e*e*e+1),"easeInOutCubic"===t&&(n=.5>e?4*e*e*e:(e-1)*(2*e-2)*(2*e-2)+1),"easeInQuart"===t&&(n=e*e*e*e),"easeOutQuart"===t&&(n=1- --e*e*e*e),"easeInOutQuart"===t&&(n=.5>e?8*e*e*e*e:1-8*--e*e*e*e),"easeInQuint"===t&&(n=e*e*e*e*e),"easeOutQuint"===t&&(n=1+--e*e*e*e*e),"easeInOutQuint"===t&&(n=.5>e?16*e*e*e*e*e:1+16*--e*e*e*e*e),n||e},f=function(t,e,n){var o=0;if(t.offsetParent)do o+=t.offsetTop,t=t.offsetParent;while(t);return o=o-e-n,o>=0?o:0},l=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},d=function(t){return t&&"object"==typeof JSON&&"function"==typeof JSON.parse?JSON.parse(t):{}},h=function(t,e){history.pushState&&(e||"true"===e)&&history.pushState({pos:t.id},"",window.location.pathname+t)};n.animateScroll=function(e,n,o){var a=c(a||r,o||{}),u=d(e?e.getAttribute("data-options"):null);a=c(a,u),n="#"+i(n.substr(1));var p,m,b,v=document.querySelector("[data-scroll-header]"),g=null===v?0:v.offsetHeight+v.offsetTop,O=t.pageYOffset,y=f(document.querySelector(n),g,parseInt(a.offset,10)),I=y-O,S=l(),A=0;h(n,a.updateURL);var Q=function(o,r,c){var u=t.pageYOffset;(o==r||u==r||t.innerHeight+u>=S)&&(clearInterval(c),a.callbackAfter(e,n))},C=function(){A+=16,m=A/parseInt(a.speed,10),m=m>1?1:m,b=O+I*s(a.easing,m),t.scrollTo(0,Math.floor(b)),Q(b,y,p)},H=function(){a.callbackBefore(e,n),p=setInterval(C,16)};0===t.pageYOffset&&t.scrollTo(0,0),H()};var p=function(t){var o=u(t.target,"[data-scroll]");o&&"a"===o.tagName.toLowerCase()&&(t.preventDefault(),n.animateScroll(o,o.hash,e,t))};return n.destroy=function(){e&&(document.removeEventListener("click",p,!1),e=null)},n.init=function(t){o&&(n.destroy(),e=c(r,t||{}),document.addEventListener("click",p,!1))},n}); -------------------------------------------------------------------------------- /src/_posts/011-component.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 0.11 Component Tips 3 | date: 2014-12-08 15:02:14 4 | tags: 5 | --- 6 | 7 |

    Note: this post contains information for the outdated 0.11 version. Please refer to the [0.12 release notes](https://github.com/yyx990803/vue/releases) for the changes in the API.

    8 | 9 | The release of 0.11 introduced [many changes](https://github.com/yyx990803/vue/blob/master/changes.md), but the most important one is how the new component scope works. Previously in 0.10.x, components have inherited scope by default. That means in a child component template you can reference parent scope properties. This often leads to tightly-coupled components, where a child component assumes knowledge of what properties are present in the parent scope. It is also possible to accidentally refer to a parent scope property in a child component. 10 | 11 | 12 | 13 | ### Isolated Scope and Data Passing 14 | 15 | Starting in 0.11, all child components have isolated scope by default, and the recommended way to control component data access is via [Explicit Data Passing](/guide/components.html#Explicit_Data_Passing) using [`v-with`](/api/directives.html#v-with) or [`paramAttributes`](/api/options.html#paramAttributes). 16 | 17 | `paramAttributes` enables us to write Web Component style templates: 18 | 19 | ``` js 20 | Vue.component('my-component', { 21 | paramAttributes: ['params'], 22 | compiled: function () { 23 | console.log(this.params) // passed from parent 24 | } 25 | }) 26 | ``` 27 | 28 | ``` html 29 | 30 | ``` 31 | 32 | ### Where Does It Belong? 33 | 34 | Previously in 0.10, all directives on a component's container element are compiled in the child component's scope. Because it inherited parent scope, this worked in most situations. Starting in 0.11.1, we want to provide a cleaner separation between component scopes. The rule of thumbs is: if something appears in the parent template, it will be compiled in parent scope; if it appears in child template, it will be compiled in child scope. For example: 35 | 36 | ``` html 37 | 38 |
    39 |

    {{parentMessage}}

    40 |
    41 | ``` 42 | 43 | ``` html 44 | 45 |
    46 |

    {{childMessage}}

    47 | 48 |
    49 | ``` 50 | 51 | Everything in the parent template will be compiled in the parent's scope, including the content that's going to be inserted into the child component. 52 | 53 | The only exception to the rule is `v-with` (and `paramAttributes` which compiles down to `v-with`), which works in both places - so you don't need to worry about it too much. 54 | 55 | ### Cleaner Event Communication 56 | 57 | Previously the standard way for a child component to communicate to its parent is via dispatching events. However, with this approach, the event listeners on the parent component are not guaranteed to be listening on the desired child component only. It's also possible to trigger undesired listners further up the chain if we do not cancel the event. 58 | 59 | The most common use case is for a parent to react to the events from a specific, direct child component. So in 0.11.4, [a new directive `v-events`](/api/directives.html#v-events) has been introduced to enable exactly this behavior. 60 | 61 | 0.11.4 has already been released, go try it out! 62 | -------------------------------------------------------------------------------- /src/_posts/why-no-template-url.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Why Vue.js doesn't support templateURL" 3 | date: 2015-10-28 10:56:00 4 | --- 5 | 6 | A very common question from new Vue users, especially those who used Angular before, is "can I have `templateURL`?". I have answered this so many times and I figure it's better to write something about it. 7 | 8 | 9 | 10 | In Angular, `templateURL` or `ng-include` allows the user to dynamically load a remote template file at runtime. This seems pretty convenient as a built-in feature, but let's rethink what problem it solves. 11 | 12 | First, it allows us to write our template in a separate HTML file. This gives us proper syntax highlighting in editors, which is probably why many prefer to do so. But is splitting your JavaScript code and the template really the best way? For a Vue.js component, its template and its JavaScript is tightly coupled by nature - it's in fact much simpler if things are just in the same file. The context switching of jumping back and forth between two files actually makes the development experience much worse. Conceptually, components are the basic building block of a Vue.js app, not templates. Every Vue.js template is coupled to an accompanying JavaScript context - there's no point in splitting them further apart. 13 | 14 | Second, because `templateURL` loads the template via Ajax at runtime, you don't need a build step in order to split up your files. This is convenient during development, but comes at a serious cost when you want to deploy it to production. Before HTTP/2 is universally supported, the number of HTTP requests is still probably the most critical factor in your app's initial load performance. Now imagine you use `templateURL` for every component in your app - the browser needs to perform dozens of HTTP requests before even being able to display anything! In case you don't know, most browsers limit the number of parallel requests it can perform to a single server. When you exceed that limit, your app's initial rendering will suffer for every extra round trip the browser has to wait for. Sure, there are build tools that can help you pre-register all those templates in `$templateCache` - but that shows us a build step is, in fact, inevitable for any serious frontend development. 15 | 16 | So, without `templateURL`, how do we deal with the development experience problem? Writing templates as inline JavaScript strings is terrible, faking templates with ` 40 | {% endraw %} 41 | 42 | 43 | ### Data Binding Dua Arah 44 | 45 | ``` html 46 |
    47 |

    {{ message }}

    48 | 49 |
    50 | ``` 51 | ``` js 52 | new Vue({ 53 | el: '#app', 54 | data: { 55 | message: 'Hello Vue.js!' 56 | } 57 | }) 58 | ``` 59 | {% raw %} 60 |
    61 |

    {{ message }}

    62 | 63 |
    64 | 72 | {% endraw %} 73 | 74 | ### Render sebuah List 75 | 76 | ``` html 77 |
    78 | 83 |
    84 | ``` 85 | ``` js 86 | new Vue({ 87 | el: '#app', 88 | data: { 89 | todos: [ 90 | { text: 'Belajar JavaScript' }, 91 | { text: 'Belajar Vue.js' }, 92 | { text: 'Buat sesuatu yang mengagumkan' } 93 | ] 94 | } 95 | }) 96 | ``` 97 | {% raw %} 98 |
    99 | 104 |
    105 | 117 | {% endraw %} 118 | 119 | 120 | ### Menangani Inputan dari Pengguna 121 | 122 | ``` html 123 |
    124 |

    {{ message }}

    125 | 126 |
    127 | ``` 128 | ``` js 129 | new Vue({ 130 | el: '#app', 131 | data: { 132 | message: 'Hello Vue.js!' 133 | }, 134 | methods: { 135 | reverseMessage: function () { 136 | this.message = this.message.split('').reverse().join('') 137 | } 138 | } 139 | }) 140 | ``` 141 | {% raw %} 142 |
    143 |

    {{ message }}

    144 | 145 |
    146 | 159 | {% endraw %} 160 | 161 | 162 | ### Lakukan Secara Bersamaan 163 | 164 | ``` html 165 |
    166 | 167 | 173 |
    174 | ``` 175 | ``` js 176 | new Vue({ 177 | el: '#app', 178 | data: { 179 | newTodo: '', 180 | todos: [ 181 | { text: 'Add some todos' } 182 | ] 183 | }, 184 | methods: { 185 | addTodo: function () { 186 | var text = this.newTodo.trim() 187 | if (text) { 188 | this.todos.push({ text: text }) 189 | this.newTodo = '' 190 | } 191 | }, 192 | removeTodo: function (index) { 193 | this.todos.splice(index, 1) 194 | } 195 | } 196 | }) 197 | ``` 198 | {% raw %} 199 |
    200 | 201 | 207 |
    208 | 231 | {% endraw %} 232 | 233 | 234 | Kami harap ini dapat memberikan Anda gambaran bagaimana Vue.js bekerja. Kami yakin anda juga memiliki banyak pertanyaan sekarang. Silakan baca terus, dan kami akan membahasnya di panduan berikutnya. 235 | -------------------------------------------------------------------------------- /src/guide/events.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Methods and Event Handling 3 | type: guide 4 | order: 9 5 | --- 6 | 7 | ## Method Handler 8 | 9 | We can use the `v-on` directive to listen to DOM events: 10 | 11 | ``` html 12 |
    13 | 14 |
    15 | ``` 16 | 17 | We are binding a click event listener to a method named `greet`. Here's how to define that method in our Vue instance: 18 | 19 | ``` js 20 | var vm = new Vue({ 21 | el: '#example', 22 | data: { 23 | name: 'Vue.js' 24 | }, 25 | // define methods under the `methods` object 26 | methods: { 27 | greet: function (event) { 28 | // `this` inside methods point to the Vue instance 29 | alert('Hello ' + this.name + '!') 30 | // `event` is the native DOM event 31 | alert(event.target.tagName) 32 | } 33 | } 34 | }) 35 | 36 | // you can invoke methods in JavaScript too 37 | vm.greet() // -> 'Hello Vue.js!' 38 | ``` 39 | 40 | Test it yourself: 41 | 42 | {% raw %} 43 |
    44 | 45 |
    46 | 63 | {% endraw %} 64 | 65 | ## Inline Statement Handler 66 | 67 | Instead of binding directly to a method name, we can also use an inline JavaScript statement: 68 | 69 | ``` html 70 |
    71 | 72 | 73 |
    74 | ``` 75 | ``` js 76 | new Vue({ 77 | el: '#example-2', 78 | methods: { 79 | say: function (msg) { 80 | alert(msg) 81 | } 82 | } 83 | }) 84 | ``` 85 | 86 | Result: 87 | {% raw %} 88 |
    89 | 90 | 91 |
    92 | 102 | {% endraw %} 103 | 104 | Similar to the restrictions on inline expressions, event handlers are restricted to **one statement only**. 105 | 106 | Sometimes we also need to access the original DOM event in an inline statement handler. You can pass it into a method using the special `$event` variable: 107 | 108 | ``` html 109 | 110 | ``` 111 | 112 | ``` js 113 | // ... 114 | methods: { 115 | say: function (msg, event) { 116 | // now we have access to the native event 117 | event.preventDefault() 118 | } 119 | } 120 | ``` 121 | 122 | ## Event Modifiers 123 | 124 | It is a very common need to call `event.preventDefault()` or `event.stopPropagation()` inside event handlers. Although we can do this easily inside methods, it would be better if the methods can be purely about data logic rather than having to deal with DOM event details. 125 | 126 | To address this problem, Vue.js provides two **event modifiers** for `v-on`: `.prevent` and `.stop`. Recall that modifiers are directive postfixes denoted by a dot: 127 | 128 | ``` html 129 | 130 | 131 | 132 | 133 |
    134 | 135 | 136 | 137 | 138 | 139 |
    140 | ``` 141 | 142 | In 1.0.16, two additional modifiers have been introduced: 143 | 144 | ``` html 145 | 146 |
    ...
    147 | 148 | 149 | 150 |
    ...
    151 | ``` 152 | 153 | ## Key Modifiers 154 | 155 | When listening for keyboard events, we often need to check for common key codes. Vue.js also allows adding key modifiers for `v-on` when listening for key events: 156 | 157 | ``` html 158 | 159 | 160 | ``` 161 | 162 | Remembering all the keyCodes is a hassle, so Vue.js provides aliases for most commonly used keys: 163 | 164 | ``` html 165 | 166 | 167 | 168 | 169 | 170 | ``` 171 | 172 | Here's the full list of key modifier aliases: 173 | 174 | - enter 175 | - tab 176 | - delete 177 | - esc 178 | - space 179 | - up 180 | - down 181 | - left 182 | - right 183 | 184 | **1.0.8+:** Single letter key aliases are also supported. 185 | 186 | **1.0.17+:** You can also define custom key modifier aliases: 187 | 188 | ``` js 189 | // enable @keyup.f1 190 | Vue.directive('on').keyCodes.f1 = 112 191 | ``` 192 | 193 | ## Why Listeners in HTML? 194 | 195 | You might be concerned that this whole event listening approach violates the good old rules about "separation of concern". Rest assured - since all Vue.js handler functions and expressions are strictly bound to the ViewModel that's handling the current View, it won't cause any maintenance difficulty. In fact, there are several benefits in using `v-on`: 196 | 197 | 1. It makes it easier to locate the handler function implementations within your JS code by simply skimming the HTML template. 198 | 199 | 2. Since you don't have to manually attach event listeners in JS, your ViewModel code can be pure logic and DOM-free. This makes it easier to test. 200 | 201 | 3. When a ViewModel is destroyed, all event listeners are automatically removed. You don't need to worry about cleaning it up yourself. 202 | -------------------------------------------------------------------------------- /src/guide/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Instalasi 3 | type: guide 4 | order: 0 5 | vue_version: 1.0.26 6 | dev_size: "266.44" 7 | min_size: "75.01" 8 | gz_size: "26.03" 9 | --- 10 | 11 | ### Catatan Kompatibilitas 12 | 13 | 14 | Vue.js **tidak mendukung** IE8 dan di bawahnya, karena Vue.js memakai fitur ECMAScript 5 yang dapat berjalan di IE8. Akan tetapi, Vue.js mendukung semua [browser yang dapat menjalankan ECMAScript 5](http://caniuse.com/#feat=es5). 15 | 16 | ### Catatan Rilis 17 | 18 | 19 | Detil catatan rilis untuk setiap versi tersedia di [GitHub](https://github.com/vuejs/vue/releases). 20 | 21 | ## Standalone 22 | 23 | 24 | Download dengan mudah dan cukup masukkan ke dalam tag ` 54 | {% endraw %} 55 | 56 | 57 | Di sini kita mendeklarasikan sebuah computed property `b`. Fungsi yang kami sediakan akan digunakan sebagai getter function untuk property `vm.b`: 58 | 59 | ``` js 60 | console.log(vm.b) // -> 2 61 | vm.a = 2 62 | console.log(vm.b) // -> 3 63 | ``` 64 | 65 | 66 | Anda dapat membuka console dan bermain dengan contoh vm yang Anda buat sendiri. Value dari `vm.b` selalu bergantung pada value dari `vm.a` 67 | 68 | 69 | Anda dapat melakukan data-bind untuk computed property di dalam template seperti property normal biasa. Vue.js tahu bahwa `vm.b` tergantung pada `vm.a`, jadi ia akan meng-update setap binding yang bergantung pada `vm.b` ketika value `vm.a` berubah. Dan bagian terbaiknya adalah kita membuat dependency relationship (ketergantungan yang saling berhubungan) ini secara deklaratif: computed getter function murni dan tanpa efek samping, yang mana hal tersebut membuatnya menjadi mudah digunakan. 70 | 71 | ### Computed Property vs. $watch 72 | 73 | 74 | Vue.js juga menyediakan method API yang bernama `$watch` yang mengizinkan Anda untuk mengamati perubahan data pada Vue instance. Ketika Anda memiliki beberapa data yang perlu berubah berdasarkan data yang lain, cobalah untuk menggunakan `$watch` - terutama jika Anda sebelumnya sudah terbiasa dengan AngularJS. Bagaimanapun, merupakan ide yang bagus untuk menggunakan computed property daripada menggunakan `$watch` callback yang impoeratif itu. Perhatikan contoh berikut: 75 | 76 | ``` html 77 |
    {{fullName}}
    78 | ``` 79 | 80 | ``` js 81 | var vm = new Vue({ 82 | el: '#demo', 83 | data: { 84 | firstName: 'Foo', 85 | lastName: 'Bar', 86 | fullName: 'Foo Bar' 87 | } 88 | }) 89 | 90 | vm.$watch('firstName', function (val) { 91 | this.fullName = val + ' ' + this.lastName 92 | }) 93 | 94 | vm.$watch('lastName', function (val) { 95 | this.fullName = this.firstName + ' ' + val 96 | }) 97 | ``` 98 | 99 | 100 | Kode di atas adalah kode yang impoeratif dan repetitif. Bandingkan dengan versi computed property seperti di bawah ini: 101 | 102 | ``` js 103 | var vm = new Vue({ 104 | el: '#demo', 105 | data: { 106 | firstName: 'Foo', 107 | lastName: 'Bar' 108 | }, 109 | computed: { 110 | fullName: function () { 111 | return this.firstName + ' ' + this.lastName 112 | } 113 | } 114 | }) 115 | ``` 116 | 117 | 118 | Lebih baik, bukan? 119 | 120 | ### Computed Setter 121 | 122 | 123 | Computed properties pada mulanya hanyalah sebuah getter (getter-only), akan tetapi Anda juga dapat menyediakan sebuah setter ketika membutuhkannya: 124 | 125 | ``` js 126 | // ... 127 | computed: { 128 | fullName: { 129 | // getter 130 | get: function () { 131 | return this.firstName + ' ' + this.lastName 132 | }, 133 | // setter 134 | set: function (newValue) { 135 | var names = newValue.split(' ') 136 | this.firstName = names[0] 137 | this.lastName = names[names.length - 1] 138 | } 139 | } 140 | } 141 | // ... 142 | ``` 143 | 144 | 145 | Sekarang ketika Anda memanggil `vm.fullName = 'John Doe'`, setter tersebut akan terpanggil dan `vm.firstName` dan `vm.lastName`juga akan ikut terbaharui. 146 | 147 | 148 | Detil teknis dibalik cara kerja computed property [didiskusikan halaman yang lain](reactivity.html#Inside-Computed-Properties) yang membahas tentang reactivity system (sistem reaktifitas). 149 | -------------------------------------------------------------------------------- /themes/vue/source/js/common.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | 3 | initSearch() 4 | initMobileMenu() 5 | if (PAGE_TYPE) { 6 | initVersionSelect() 7 | initSubHeaders() 8 | } 9 | 10 | /** 11 | * Swiftype search box 12 | */ 13 | 14 | function initSearch () { 15 | docsearch({ 16 | appId: 'BH4D9OD16A', 17 | apiKey: '85cc3221c9f23bfbaa4e3913dd7625ea', 18 | indexName: 'vuejs', 19 | inputSelector: '#search-query' 20 | }); 21 | } 22 | 23 | /** 24 | * Mobile burger menu button for toggling sidebar 25 | */ 26 | 27 | function initMobileMenu () { 28 | var mobileBar = document.getElementById('mobile-bar') 29 | var sidebar = document.querySelector('.sidebar') 30 | var menuButton = mobileBar.querySelector('.menu-button') 31 | 32 | menuButton.addEventListener('click', function () { 33 | sidebar.classList.toggle('open') 34 | }) 35 | 36 | document.body.addEventListener('click', function (e) { 37 | if (e.target !== menuButton && !sidebar.contains(e.target)) { 38 | sidebar.classList.remove('open') 39 | } 40 | }) 41 | } 42 | 43 | /** 44 | * Doc version select 45 | */ 46 | 47 | function initVersionSelect () { 48 | // version select 49 | document.querySelector('.version-select').addEventListener('change', function (e) { 50 | var version = e.target.value 51 | if (version.indexOf('1.') !== 0) { 52 | version = version.replace('.', '') 53 | var section = window.location.pathname.match(/\/(\w+?)\//)[1] 54 | window.location.assign('http://' + version + '.vuejs.org/' + section + '/') 55 | } else { 56 | // TODO when 1.x is out 57 | } 58 | }) 59 | } 60 | 61 | /** 62 | * Sub headers in sidebar 63 | */ 64 | 65 | function initSubHeaders () { 66 | var each = [].forEach 67 | var main = document.getElementById('main') 68 | var header = document.getElementById('header') 69 | var sidebar = document.querySelector('.sidebar') 70 | var content = document.querySelector('.content') 71 | 72 | // build sidebar 73 | var currentPageAnchor = sidebar.querySelector('.sidebar-link.current') 74 | var isAPI = document.querySelector('.content').classList.contains('api') 75 | if (currentPageAnchor || isAPI) { 76 | var allHeaders = [] 77 | var sectionContainer 78 | if (isAPI) { 79 | sectionContainer = document.querySelector('.menu-root') 80 | } else { 81 | sectionContainer = document.createElement('ul') 82 | sectionContainer.className = 'menu-sub' 83 | currentPageAnchor.parentNode.appendChild(sectionContainer) 84 | } 85 | var headers = content.querySelectorAll('h2') 86 | if (headers.length) { 87 | each.call(headers, function (h) { 88 | sectionContainer.appendChild(makeLink(h)) 89 | var h3s = collectH3s(h) 90 | allHeaders.push(h) 91 | allHeaders.push.apply(allHeaders, h3s) 92 | if (h3s.length) { 93 | sectionContainer.appendChild(makeSubLinks(h3s, isAPI)) 94 | } 95 | }) 96 | } else { 97 | headers = content.querySelectorAll('h3') 98 | each.call(headers, function (h) { 99 | sectionContainer.appendChild(makeLink(h)) 100 | allHeaders.push(h) 101 | }) 102 | } 103 | 104 | var animating = false 105 | sectionContainer.addEventListener('click', function (e) { 106 | e.preventDefault() 107 | if (e.target.classList.contains('section-link')) { 108 | sidebar.classList.remove('open') 109 | setActive(e.target) 110 | animating = true 111 | setTimeout(function () { 112 | animating = false 113 | }, 400) 114 | } 115 | }, true) 116 | 117 | // make links clickable 118 | allHeaders.forEach(makeHeaderClickable) 119 | 120 | // init smooth scroll 121 | smoothScroll.init({ 122 | speed: 400, 123 | offset: window.innerWidth > 720 124 | ? 40 125 | : 58 126 | }) 127 | } 128 | 129 | // listen for scroll event to do positioning & highlights 130 | window.addEventListener('scroll', updateSidebar) 131 | window.addEventListener('resize', updateSidebar) 132 | 133 | function updateSidebar () { 134 | var doc = document.documentElement 135 | var top = doc && doc.scrollTop || document.body.scrollTop 136 | var headerHeight = header.offsetHeight 137 | if (top > headerHeight) { 138 | main.className = 'fix-sidebar' 139 | } else { 140 | main.className = '' 141 | } 142 | if (animating || !allHeaders) return 143 | var last 144 | for (var i = 0; i < allHeaders.length; i++) { 145 | var link = allHeaders[i] 146 | if (link.offsetTop > top) { 147 | if (!last) last = link 148 | break 149 | } else { 150 | last = link 151 | } 152 | } 153 | if (last) 154 | setActive(last.id) 155 | } 156 | 157 | function makeLink (h) { 158 | var link = document.createElement('li') 159 | var text = h.textContent.replace(/\(.*\)$/, '') 160 | link.innerHTML = 161 | '
    ' + 162 | text + 163 | '' 164 | return link 165 | } 166 | 167 | function collectH3s (h) { 168 | var h3s = [] 169 | var next = h.nextSibling 170 | while (next && next.tagName !== 'H2') { 171 | if (next.tagName === 'H3') { 172 | h3s.push(next) 173 | } 174 | next = next.nextSibling 175 | } 176 | return h3s 177 | } 178 | 179 | function makeSubLinks (h3s, small) { 180 | var container = document.createElement('ul') 181 | if (small) { 182 | container.className = 'menu-sub' 183 | } 184 | h3s.forEach(function (h) { 185 | container.appendChild(makeLink(h)) 186 | }) 187 | return container 188 | } 189 | 190 | function setActive (id) { 191 | var previousActive = sidebar.querySelector('.section-link.active') 192 | var currentActive = typeof id === 'string' 193 | ? sidebar.querySelector('.section-link[href="#' + id + '"]') 194 | : id 195 | if (currentActive !== previousActive) { 196 | if (previousActive) previousActive.classList.remove('active') 197 | currentActive.classList.add('active') 198 | } 199 | } 200 | 201 | function makeHeaderClickable (link) { 202 | var wrapper = document.createElement('a') 203 | wrapper.href = '#' + link.id 204 | wrapper.setAttribute('data-scroll', '') 205 | link.parentNode.insertBefore(wrapper, link) 206 | wrapper.appendChild(link) 207 | } 208 | } 209 | })() 210 | -------------------------------------------------------------------------------- /themes/vue/layout/index.ejs: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 10 |
    11 | 12 |

    Vue.js

    13 |
    14 | 15 |

    Komponen Reaktif untuk Antarmuka Web yang Modern

    16 |

    17 | Install v<%- theme.vue_version %> 18 | Memulai 19 |

    20 | 31 | 32 | 39 | 40 |
    41 | <%- partial('partials/sponsors') %> 42 |
    43 |
    44 | 45 |
    46 |
    47 | 48 |
    49 | <%- partial('partials/sponsors') %> 50 |
    51 | 52 |
    53 | 54 |

    Contoh Sederhana

    55 |
    56 |
    1
     57 | 2
     58 | 3
     59 | 4
     60 | 
    <div id="demo">
     61 |   <p>{{message}}</p>
     62 |   <input v-model="message">
     63 | </div>
     64 | 
    65 |
    66 | 67 |
    +
    68 | 69 |
    70 |
    1
     71 | 2
     72 | 3
     73 | 4
     74 | 5
     75 | 6
     76 | 
    var demo = new Vue({
     77 |   el: '#demo',
     78 |   data: {
     79 |     message: 'Hello Vue.js!'
     80 |   }
     81 | })
     82 | 
    83 |
    84 | 85 |
    =
    86 | 87 |
    88 |
    89 |

    {{message}}

    90 | 91 |
    92 | 100 |
    101 |
    102 |
    103 |
    104 |
    105 | 106 |

    Simpel

    107 | 108 |

    Cukup tulis beberapa kode HTML, ambil beberapa JSON, dan buat instance Vue.

    109 |
    110 |
    111 |

    Reaktif

    112 |

    Expressions & computed properties with transparent dependency tracking.

    113 |
    114 |
    115 | 116 |

    Komponen-komponen

    117 | 118 |

    Buat aplikasi Anda dengan komponen yang terpisah dan dapat digunakan ulang.

    119 |
    120 |
    121 | 122 |

    Padat

    123 | 124 |

    ~24kb min+gzip, tanpa dependency.

    125 |
    126 |
    127 | 128 |

    Cepat

    129 | 130 |

    Async batch DOM updates yang presisi dan efisien.

    131 |
    132 |
    133 | 134 |

    Siap Pakai

    135 | 136 |

    Install melalui NPM atau Bower, tergantung ekosistem favorit Anda

    137 |
    138 |
    139 |
    140 |
    141 | 142 |

    Anda harus mencoba Vue.js jika menginginkan:

    143 | 150 | 157 |
    158 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /src/guide/class-and-style.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Class and Style Bindings 3 | type: guide 4 | order: 6 5 | --- 6 | 7 | 8 | Salah satu kebutuhan umum dari data binding adalah memanipulasi sebuah daftar class elemen dan inline styles. Karena kedua-duanya merupakan atribut, kita bisa menggunakan `v-bind` untuk menangani mereka: kita hanya perlu melakukan perhitungan/kalkulasi sebuah string akhir dengan ekspresi kita. Namun, mencampur dengan penggabungan string membosankan dan rentan error. Untuk alasan inilah, Vue.js menyediakan tambahan spesial ketika `v-bind` digunakan untuk `class` dan `style`. Selain untuk Strings, ekpresi tersebut juga bisa mengevaluasi Objek dan Larik/Array. 9 | 10 | ## Binding HTML Classes 11 | 12 | 13 |

    Meskipun anda bisa menggunakan interpolasi kurung kurawal ganda seperti `{% raw %}class="{{ className }}"{% endraw %}` untuk mengikat class, tidak dianjurkan untuk mencampur syle tersebut dengan `v-bind:class`. Gunakan salah satu atau yang lainnya!

    14 | 15 | ### Objek Sintaks 16 | 17 | 18 | Kita bisa melewatkan sebuah Objek ke `v-bind:class` untuk secara dinamis men-toggle class. Catatan bahwa `v-bind:class` directive dapat berdampingan dengan plain `class` attribute: 19 | 20 | ``` html 21 |
    22 | ``` 23 | ``` js 24 | data: { 25 | isA: true, 26 | isB: false 27 | } 28 | ``` 29 | 30 | 31 | Yang akan merender: 32 | 33 | ``` html 34 |
    35 | ``` 36 | 37 | 38 | Ketika `isA` dan `isB` berubah, daftar class juga akan berubah. Sebagai contoh, jika `isB` menjadi `true`, daftar kelas akan menjadi `"static class-a class-b"`. 39 | 40 | 41 | Dan anda juga bisa secara langsung mengikat ke sebuah objek di dalam sebuah data: 42 | 43 | ``` html 44 |
    45 | ``` 46 | ``` js 47 | data: { 48 | classObject: { 49 | 'class-a': true, 50 | 'class-b': false 51 | } 52 | } 53 | ``` 54 | 55 | 56 | Ini akan merender hasil yang sama. Seperti yang mungkin anda telah sadari, kita juga bisa mengikat ke sebuah [computed property](computed.html) yang mengembalikan sebuah Objek. Ini adalah sebuah hal yang lumrah dan merupakan pola yang powerfull. 57 | 58 | ### Sintaks Larik/Array 59 | 60 | 61 | Kita bisa melewatkan sebuah larik/array ke `v-bind:class` untuk menerapkan sebuah daftar class: 62 | 63 | ``` html 64 |
    65 | ``` 66 | ``` js 67 | data: { 68 | classA: 'class-a', 69 | classB: 'class-b' 70 | } 71 | ``` 72 | 73 | 74 | Yang akan merender: 75 | 76 | ``` html 77 |
    78 | ``` 79 | 80 | 81 | Jika anda juga ingin men-toggle sebuah class di daftar secara kondisional, anda bisa melakukannya dengan sebuah ekpresi ternari: 82 | 83 | ``` html 84 |
    85 | ``` 86 | 87 | 88 | Ini akan selalu menerapkan `classA`, tetapi hanya akan menerapkan `classB` ketika `isB` bernilai `true`. 89 | 90 | 91 | Meskipun demikian, ini bisa menjadi sedikit berlebihan dalam penulisan jika anda memiliki banyak kondisi class. Pada versi 1.0.19+, memungkinkan untuk menggunakan Sintaks Objek didalam Sintaks larik/array: 92 | 93 | 94 | ``` html 95 |
    96 | ``` 97 | 98 | ## Binding Inline Styles 99 | 100 | ### Sintaks Objek 101 | 102 | 103 | Sintaks objek untuk `v-bind:style` sangat mudah dan jelas - dia mirip dengan CSS, kecuali dia adalah objek Javascript. Anda bisa menggunakan camelCase atau kebab-case untuk nama properti CSS: 104 | 105 | 106 | ``` html 107 |
    108 | ``` 109 | ``` js 110 | data: { 111 | activeColor: 'red', 112 | fontSize: 30 113 | } 114 | ``` 115 | 116 | 117 | Sering kali mengikat sebuah object style secara langsung merupakan ide yang bagus sehingga template menjadi lebih rapi. 118 | 119 | ``` html 120 |
    121 | ``` 122 | ``` js 123 | data: { 124 | styleObject: { 125 | color: 'red', 126 | fontSize: '13px' 127 | } 128 | } 129 | ``` 130 | 131 | 132 | Sekali lagi, Sintaks objek sering kali digunakan serangkai dengan computed properties yang mengembalikan Objek. 133 | 134 | ### Sintaks Larik/Array 135 | 136 | 137 | Sintaks larik/array untuk `v-bind:Style` membolehkan anda untuk menerapkan banyak style objects ke element yang sama: 138 | 139 | ``` html 140 |
    141 | ``` 142 | 143 | ### Auto-prefixing 144 | 145 | 146 | Ketika anda menggunakan sebuah properti CSS yang memerlukan awalan vendor pada `v-bind:style`, sebagai contoh `transform`, Vue.js akan secara otomatis mendeteksi dan menambahkan awalan yang sesuai untuk style yang diterapkan. 147 | -------------------------------------------------------------------------------- /src/_posts/012-release.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Vue.js 0.12 released! 3 | date: 2015-06-11 17:37:30 4 | --- 5 | 6 | I'm really excited to announce that [Vue.js 0.12: Dragon Ball](https://github.com/yyx990803/vue/releases/tag/0.12.0) is finally here! Thanks to everyone who tried out the beta/rc versions and provided feedback / bug reports along the way. 7 | 8 | There's a lot to cover in this release, and we will talk about a few highlights below. However, it is still recommended to carefully go through the [Full Release Note](https://github.com/yyx990803/vue/releases/tag/0.12.0) and updated docs if you are upgrading from 0.11. You can report bugs on GitHub, send questions to [vuejs/Discussion](https://github.com/vuejs/Discussion/issues), or join us in the [Gitter chat channel](https://gitter.im/yyx990803/vue). 9 | 10 | 11 | 12 | ### More Consistent Component Syntax 13 | 14 | Previously in 0.11 you have two ways to use a Vue.js component: using the `v-component` directive, or using custom elements. There are also two ways to pass data down to child components: using the `v-with` directive, or using the `paramAttributes` option. Although both custom elements and param attributes get compiled down to directives eventually, it is confusing and redundant to have two sets of syntax for the same functionality. 15 | 16 | In addition, it should be noted that the component system is a first-class concept in Vue.js, even more important than directives. It defines how we encapsulate our higher-level view logic and compose our application. In the meanwhile, having a clear and declarative way to pass data into child components is also very important. Components and param attributes really deserve their own dedicated syntax to differentiate from other directives. 17 | 18 | As a result, `v-component` and `v-with` have been deprecated in 0.12. `paramAttributes` has also been renamed to `props`, which is shorter and cleaner. From now on, most Vue.js components will look like this: 19 | 20 | ``` html 21 | 22 | ``` 23 | 24 | There are also additional props-related improvements such as explicit one-time or one-way props, expression as props, methods as prop callbacks and more. You can find out more details in the 0.12 release notes linked above and the updated [Component System](/guide/components.html) section of the guide. 25 | 26 | ### Filter Arguments Improvements 27 | 28 | In 0.11, filters always receive their arguments as plain strings. An argument can be enclosed in quotes to include whitespace, but the quotes are not automatically stripped when passed into the filter function. Some users were also confused about how to retrive a dynamic value on the vm instead of a plain string. 29 | 30 | In 0.12, the filter argument syntax now follows a simple rule: if an argument is enclosed in quotes, it will be passed in as a plain string; otherwise, it will be evaluated against the current vm as a dynamic value. 31 | 32 | This means the usage of some existing filters will have to change: 33 | 34 | ``` html 35 | 36 | {{ items.length | pluralize 'item' }} 37 | ``` 38 | 39 | But it would make custom filters that rely on dynamic values much easier to write: 40 | 41 | ``` html 42 | {{ msg | concat otherMsg }} 43 | ``` 44 | 45 | Here the first argument to the `concat` filter will be the value of `this.otherMsg`. 46 | 47 | ### Asynchronous Components 48 | 49 | It is common practice to bundle all the JavaScript into one file when building large single page applications. But when the file becomes too large, we may want to defer loading parts of our application for a faster initial load. However, this does pose some constraints on how the application architecture should be designed. It could be very tricky to figure out how to properly split up your JavaScript bundles. 50 | 51 | Well, with Vue.js we can already build our applications as decoupled components. If we can lazily load a dynamic component only when it is needed, wouldn't it be awesome? As a matter of fact, in 0.12 this would be trivially easy with the new Asynchronous Component feature. 52 | 53 | In 0.12, you can define a component as a factory function that asynchronously resolves a component definition (can be just a plain options object). Vue.js will only trigger the factory function when the component actually needs to be rendered, and will cache the result for future re-renders: 54 | 55 | ``` js 56 | Vue.component('async-example', function (resolve, reject) { 57 | setTimeout(function () { 58 | resolve({ 59 | template: '
    I am async!
    ' 60 | }) 61 | }, 1000) 62 | }) 63 | ``` 64 | 65 | It is up to you to decide how to load the component from the server, e.g. `$.getScript()` or require.js; but the recommended usage is to pair it up with Webpack's [Code Splitting feature](http://webpack.github.io/docs/code-splitting.html): 66 | 67 | ``` js 68 | Vue.component('async-webpack-example', function (resolve, reject) { 69 | // In Webpack AMD like syntax indicates a code split point 70 | require(['./my-async-component'], resolve) 71 | }) 72 | ``` 73 | 74 | That's all you need to do. You can use the component just like before, without even thinking about it being async. Webpack will automatically split your final JavaScript into separate bundles with correct dependencies, and automatically load a bundle via Ajax when it is required. You can check out a fully functional example [here](https://github.com/vuejs/vue-webpack-example). 75 | 76 | ### Improved Transition System 77 | 78 | Vue.js' transition system is really easy to use, but in the past it has the limitation that you cannot mix CSS and JavaScript-based transitions together. In 0.12 that is no longer the case! The improved transition system now allows you to add JavaScript hooks to a CSS-based transition for additional control. The amount of hooks exposed have also been expanded to give you finer-grained control at every stage of the transition. 79 | 80 | `v-repeat` now also ships with built-in support for staggering transitions. It is as simple as adding `stagger="100"` to your repeated element. It is also possible to define separate staggering for enter and leaving, or even dynamically calculate the staggering delay in a JavaScript hook. 81 | 82 | For full details on the new transition system, check out the [updated guide](/guide/transitions.html). 83 | 84 | ### Performance Tuning 85 | 86 | Vue.js' precise dependency tracking makes it the one of the most efficient view layer for small hot updates, but there's always room for improvement. In 0.12, internal instance creation and compilation refactors have improved first-render performance for large lists by up to 40%. With proper `track-by` usage, [re-rendering with large, brand new dataset](http://vuejs.github.io/js-repaint-perfs/vue/) is also comparable to, or even faster than other Virtual-DOM based frameworks. 87 | 88 | ### One More Thing... 89 | 90 | With 0.12 out of the door, more efforts will now be spent on the official vue-router, a dedicated routing library for Vue.js with nested view matching, full transition support, and asynchronous data hooks. I have expressed that Vue.js core intends to stay as a no-frills, drop-in view layer library, and that will not change. The vue-router will be shipped separately and is totally optional, however you can expect it to work seamlessly with Vue.js core when you need it. 91 | -------------------------------------------------------------------------------- /src/guide/instance.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Vue Instance 3 | type: guide 4 | order: 3 5 | --- 6 | 7 | #Konstruktor 8 | 9 | 10 | Setiap aplikasi Vue.js dibootstrapp dengan membuat sebuah **root Vue Instance** dengan fungsi konstruktor `Vue`: 11 | 12 | ``` js 13 | var vm = new Vue({ 14 | // options 15 | }) 16 | ``` 17 | 18 | 19 | Sebuah Vue instance secara esensial adalah **ViewModel** seperti yang didefinisikan di pola [MVVM](https://en.wikipedia.org/wiki/Model_View_ViewModel), jadi variabel bernama `vm` akan sering anda lihat sepanjang dokumentasi. 20 | 21 | 22 | Ketika anda menginstant sebuah Vue instance, anda perlu melewatkan sebuah **options object** yang dapat menampung opsi untuk data, template, elemen untuk dikaitkan, metode, lifecycle callbacks, dll. Daftar lengkap opsi tersebut bisa dilihat di [referensi API](/api). 23 | 24 | 25 | Konstruktor `Vue` dapat diperluas untuk membuat **component constructors** yang dapat digunakan ulang kembali dengan opsi yang telah didefinisikan sebelumnya: 26 | 27 | ``` js 28 | var MyComponent = Vue.extend({ 29 | // extension options 30 | }) 31 | 32 | // semua instance `MyComponent` dibuat oleh 33 | // opsi yang telah didefinisikan sebelumnya 34 | var myComponentInstance = new MyComponent() 35 | ``` 36 | 37 | 38 | Meskipun anda bisa membuat instance yang diperluas secara imperatif, dalam banyak kasus anda akan mendaftarkan sebuah konstruktor komponen sebagai custom element dan menyusunnya di template secara deklaratif. Kita akan membahas tentang sistem komponen secara detail nanti. Untuk sekarang, anda hanya perlu tahu bahwa semua komponen Vue.js pada dasarnya merupakan perluasan Vue instances. 39 | 40 | ## Properti and Methods 41 | 42 | 43 | Setiap Vue instance **proxies** semua properti yang ada di objek `data`: 44 | ``` js 45 | var data = { a: 1 } 46 | var vm = new Vue({ 47 | data: data 48 | }) 49 | 50 | vm.a === data.a // -> true 51 | 52 | // merubah setting properti juga mempengaruhi data asli 53 | vm.a = 2 54 | data.a // -> 2 55 | 56 | // ... dan juga sebaliknya 57 | data.a = 3 58 | vm.a // -> 3 59 | ``` 60 | 61 | 62 | Perlu diperhatikan bahwa hanya proxied properties yang **reaktif**. Jika anda menyematkan sebuah properti baru ke instance setelah instance tersebut dibuat, instance tersebut tidak akan memicu apapun perubahan yang terjadi pada tampilan. Kita akan membahas tentang reactivity system secara detail nanti. 63 | 64 | 65 | Sebagai tambahan untuk properti data, Vue instance mempunyai beberapa instance properti dan methods yang berguna. Properti dan methods ini diawali dengan `$` untuk membedakan dari proxied data properties. Sebgai contoh: 66 | 67 | ``` js 68 | var data = { a: 1 } 69 | var vm = new Vue({ 70 | el: '#example', 71 | data: data 72 | }) 73 | 74 | vm.$data === data // -> true 75 | vm.$el === document.getElementById('example') // -> true 76 | 77 | // $watch adalah sebuah contoh instance method 78 | vm.$watch('a', function (newVal, oldVal) { 79 | // callback ini akan dipanggil ketika `vm.a` berubah 80 | }) 81 | ``` 82 | 83 | 84 | Silahkan lihat [referensi API](/api) untuk mengetahui daftar lengkap instance properties dan methods. 85 | 86 | ## Siklus Hidup Vue Instance 87 | 88 | 89 | Setiap Vue instance melalui sebuah rangkaian langkah-langkah inisialisasi ketika dia dibuat - sebagai contoh, dia perlu untuk mempersiapkan observasi data, kompilasi template, dan membuat ikatan data yang diperlukan. Selama proses berlangsung, dia juga akan meminta beberapa **lifecycle hooks**, yang akan memberikan kita kesempatan untuk mengeksekusi custom logic. Sebagai contoh, `created` hook dipanggil setelah instance dibuat. 90 | 91 | 92 | ``` js 93 | var vm = new Vue({ 94 | data: { 95 | a: 1 96 | }, 97 | created: function () { 98 | // `this` menunjuk kepada vm instance 99 | console.log('a is: ' + this.a) 100 | } 101 | }) 102 | // -> "a is: 1" 103 | ``` 104 | 105 | 106 | Ada juga hook/pengaitan lain yang akan dipanggil pada keadaan yang berbeda dari siklus hidup instance, sebagai contoh `compiled`, `ready`, dan `destroyed`. Semua siklus hidup hook/pengaitan dipanggil dengan `this` konteks yang menunjuk ke Vue instance yang memanggilnya. Beberapa pengguna mungkin bertanya-tanya dimana konsep "controller" berada di Vue.js, dan jawabannya adalah: tidak ada controller/pengendali di Vue.js. Custom logic anda untuk sebuah komponen akan dipisah di antara siklus hidup hook/pengaitan. 107 | 108 | ## Diagram Siklus Hidup 109 | 110 | 111 | Di bawah ini adalah sebuah diagram siklus hidup instance. Untuk sekarang anda tidak perlu memahaminya secara keseluruhan, tetapi diagram ini nantinya akan berguna suatu hari nanti. 112 | 113 | ![Siklus Hidup](/images/lifecycle.png) 114 | -------------------------------------------------------------------------------- /todomvc/node_modules/todomvc-app-css/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | button { 8 | margin: 0; 9 | padding: 0; 10 | border: 0; 11 | background: none; 12 | font-size: 100%; 13 | vertical-align: baseline; 14 | font-family: inherit; 15 | font-weight: inherit; 16 | color: inherit; 17 | -webkit-appearance: none; 18 | appearance: none; 19 | -webkit-font-smoothing: antialiased; 20 | -moz-font-smoothing: antialiased; 21 | font-smoothing: antialiased; 22 | } 23 | 24 | body { 25 | font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; 26 | line-height: 1.4em; 27 | background: #f5f5f5; 28 | color: #4d4d4d; 29 | min-width: 230px; 30 | max-width: 550px; 31 | margin: 0 auto; 32 | -webkit-font-smoothing: antialiased; 33 | -moz-font-smoothing: antialiased; 34 | font-smoothing: antialiased; 35 | font-weight: 300; 36 | } 37 | 38 | button, 39 | input[type="checkbox"] { 40 | outline: none; 41 | } 42 | 43 | .hidden { 44 | display: none; 45 | } 46 | 47 | .todoapp { 48 | background: #fff; 49 | margin: 130px 0 40px 0; 50 | position: relative; 51 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 52 | 0 25px 50px 0 rgba(0, 0, 0, 0.1); 53 | } 54 | 55 | .todoapp input::-webkit-input-placeholder { 56 | font-style: italic; 57 | font-weight: 300; 58 | color: #e6e6e6; 59 | } 60 | 61 | .todoapp input::-moz-placeholder { 62 | font-style: italic; 63 | font-weight: 300; 64 | color: #e6e6e6; 65 | } 66 | 67 | .todoapp input::input-placeholder { 68 | font-style: italic; 69 | font-weight: 300; 70 | color: #e6e6e6; 71 | } 72 | 73 | .todoapp h1 { 74 | position: absolute; 75 | top: -155px; 76 | width: 100%; 77 | font-size: 100px; 78 | font-weight: 100; 79 | text-align: center; 80 | color: rgba(175, 47, 47, 0.15); 81 | -webkit-text-rendering: optimizeLegibility; 82 | -moz-text-rendering: optimizeLegibility; 83 | text-rendering: optimizeLegibility; 84 | } 85 | 86 | .new-todo, 87 | .edit { 88 | position: relative; 89 | margin: 0; 90 | width: 100%; 91 | font-size: 24px; 92 | font-family: inherit; 93 | font-weight: inherit; 94 | line-height: 1.4em; 95 | border: 0; 96 | outline: none; 97 | color: inherit; 98 | padding: 6px; 99 | border: 1px solid #999; 100 | box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); 101 | box-sizing: border-box; 102 | -webkit-font-smoothing: antialiased; 103 | -moz-font-smoothing: antialiased; 104 | font-smoothing: antialiased; 105 | } 106 | 107 | .new-todo { 108 | padding: 16px 16px 16px 60px; 109 | border: none; 110 | background: rgba(0, 0, 0, 0.003); 111 | box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); 112 | } 113 | 114 | .main { 115 | position: relative; 116 | z-index: 2; 117 | border-top: 1px solid #e6e6e6; 118 | } 119 | 120 | label[for='toggle-all'] { 121 | display: none; 122 | } 123 | 124 | .toggle-all { 125 | position: absolute; 126 | top: -55px; 127 | left: -12px; 128 | width: 60px; 129 | height: 34px; 130 | text-align: center; 131 | border: none; /* Mobile Safari */ 132 | } 133 | 134 | .toggle-all:before { 135 | content: '❯'; 136 | font-size: 22px; 137 | color: #e6e6e6; 138 | padding: 10px 27px 10px 27px; 139 | } 140 | 141 | .toggle-all:checked:before { 142 | color: #737373; 143 | } 144 | 145 | .todo-list { 146 | margin: 0; 147 | padding: 0; 148 | list-style: none; 149 | } 150 | 151 | .todo-list li { 152 | position: relative; 153 | font-size: 24px; 154 | border-bottom: 1px solid #ededed; 155 | } 156 | 157 | .todo-list li:last-child { 158 | border-bottom: none; 159 | } 160 | 161 | .todo-list li.editing { 162 | border-bottom: none; 163 | padding: 0; 164 | } 165 | 166 | .todo-list li.editing .edit { 167 | display: block; 168 | width: 506px; 169 | padding: 13px 17px 12px 17px; 170 | margin: 0 0 0 43px; 171 | } 172 | 173 | .todo-list li.editing .view { 174 | display: none; 175 | } 176 | 177 | .todo-list li .toggle { 178 | text-align: center; 179 | width: 40px; 180 | /* auto, since non-WebKit browsers doesn't support input styling */ 181 | height: auto; 182 | position: absolute; 183 | top: 0; 184 | bottom: 0; 185 | margin: auto 0; 186 | border: none; /* Mobile Safari */ 187 | -webkit-appearance: none; 188 | appearance: none; 189 | } 190 | 191 | .todo-list li .toggle:after { 192 | content: url('data:image/svg+xml;utf8,'); 193 | } 194 | 195 | .todo-list li .toggle:checked:after { 196 | content: url('data:image/svg+xml;utf8,'); 197 | } 198 | 199 | .todo-list li label { 200 | white-space: pre; 201 | word-break: break-word; 202 | padding: 15px 60px 15px 15px; 203 | margin-left: 45px; 204 | display: block; 205 | line-height: 1.2; 206 | transition: color 0.4s; 207 | } 208 | 209 | .todo-list li.completed label { 210 | color: #d9d9d9; 211 | text-decoration: line-through; 212 | } 213 | 214 | .todo-list li .destroy { 215 | display: none; 216 | position: absolute; 217 | top: 0; 218 | right: 10px; 219 | bottom: 0; 220 | width: 40px; 221 | height: 40px; 222 | margin: auto 0; 223 | font-size: 30px; 224 | color: #cc9a9a; 225 | margin-bottom: 11px; 226 | transition: color 0.2s ease-out; 227 | } 228 | 229 | .todo-list li .destroy:hover { 230 | color: #af5b5e; 231 | } 232 | 233 | .todo-list li .destroy:after { 234 | content: '×'; 235 | } 236 | 237 | .todo-list li:hover .destroy { 238 | display: block; 239 | } 240 | 241 | .todo-list li .edit { 242 | display: none; 243 | } 244 | 245 | .todo-list li.editing:last-child { 246 | margin-bottom: -1px; 247 | } 248 | 249 | .footer { 250 | color: #777; 251 | padding: 10px 15px; 252 | height: 20px; 253 | text-align: center; 254 | border-top: 1px solid #e6e6e6; 255 | } 256 | 257 | .footer:before { 258 | content: ''; 259 | position: absolute; 260 | right: 0; 261 | bottom: 0; 262 | left: 0; 263 | height: 50px; 264 | overflow: hidden; 265 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 266 | 0 8px 0 -3px #f6f6f6, 267 | 0 9px 1px -3px rgba(0, 0, 0, 0.2), 268 | 0 16px 0 -6px #f6f6f6, 269 | 0 17px 2px -6px rgba(0, 0, 0, 0.2); 270 | } 271 | 272 | .todo-count { 273 | float: left; 274 | text-align: left; 275 | } 276 | 277 | .todo-count strong { 278 | font-weight: 300; 279 | } 280 | 281 | .filters { 282 | margin: 0; 283 | padding: 0; 284 | list-style: none; 285 | position: absolute; 286 | right: 0; 287 | left: 0; 288 | } 289 | 290 | .filters li { 291 | display: inline; 292 | } 293 | 294 | .filters li a { 295 | color: inherit; 296 | margin: 3px; 297 | padding: 3px 7px; 298 | text-decoration: none; 299 | border: 1px solid transparent; 300 | border-radius: 3px; 301 | } 302 | 303 | .filters li a.selected, 304 | .filters li a:hover { 305 | border-color: rgba(175, 47, 47, 0.1); 306 | } 307 | 308 | .filters li a.selected { 309 | border-color: rgba(175, 47, 47, 0.2); 310 | } 311 | 312 | .clear-completed, 313 | html .clear-completed:active { 314 | float: right; 315 | position: relative; 316 | line-height: 20px; 317 | text-decoration: none; 318 | cursor: pointer; 319 | position: relative; 320 | } 321 | 322 | .clear-completed:hover { 323 | text-decoration: underline; 324 | } 325 | 326 | .info { 327 | margin: 65px auto 0; 328 | color: #bfbfbf; 329 | font-size: 10px; 330 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 331 | text-align: center; 332 | } 333 | 334 | .info p { 335 | line-height: 1; 336 | } 337 | 338 | .info a { 339 | color: inherit; 340 | text-decoration: none; 341 | font-weight: 400; 342 | } 343 | 344 | .info a:hover { 345 | text-decoration: underline; 346 | } 347 | 348 | /* 349 | Hack to remove background from Mobile Safari. 350 | Can't use it globally since it destroys checkboxes in Firefox 351 | */ 352 | @media screen and (-webkit-min-device-pixel-ratio:0) { 353 | .toggle-all, 354 | .todo-list li .toggle { 355 | background: none; 356 | } 357 | 358 | .todo-list li .toggle { 359 | height: 40px; 360 | } 361 | 362 | .toggle-all { 363 | -webkit-transform: rotate(90deg); 364 | transform: rotate(90deg); 365 | -webkit-appearance: none; 366 | appearance: none; 367 | } 368 | } 369 | 370 | @media (max-width: 430px) { 371 | .footer { 372 | height: 50px; 373 | } 374 | 375 | .filters { 376 | bottom: 10px; 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /themes/vue/source/css/page.styl: -------------------------------------------------------------------------------- 1 | @import "_common" 2 | @import "_demo" 3 | @import "_blog" 4 | @import "_search" 5 | 6 | $header-height = 40px 7 | 8 | #header 9 | background-color #fff 10 | box-shadow 0 0 4px rgba(0,0,0,.25) 11 | padding 25px 60px 12 | position relative 13 | z-index 2 14 | 15 | #nav 16 | list-style-type none 17 | margin 0 18 | padding 0 19 | position absolute 20 | right 60px 21 | top 25px 22 | height $header-height 23 | line-height $header-height 24 | .break 25 | display none 26 | li 27 | display inline-block 28 | position relative 29 | margin 0 .6em 30 | 31 | .nav-link 32 | padding-bottom 3px 33 | &:hover, &.current 34 | border-bottom 3px solid $green 35 | 36 | #search-query 37 | height 30px 38 | line-height 30px 39 | box-sizing border-box 40 | padding 0 15px 0 30px 41 | border 1px solid #e3e3e3 42 | outline none 43 | border-radius 15px 44 | margin-right 10px 45 | transition border-color .2s ease 46 | background #fff url(/images/search.png) 8px 5px no-repeat 47 | background-size 20px 48 | &:focus 49 | border-color $green 50 | 51 | #logo 52 | display inline-block 53 | font-size 1.5em 54 | line-height $header-height 55 | color $dark 56 | font-family $logo-font 57 | font-weight 500 58 | img 59 | vertical-align middle 60 | margin-right 6px 61 | width $header-height 62 | height $header-height 63 | 64 | #mobile-bar 65 | position fixed 66 | top 0 67 | left 0 68 | width 100% 69 | height 40px 70 | background-color #fff 71 | z-index 9 72 | display none 73 | box-shadow 0 0 4px rgba(0,0,0,.25) 74 | .menu-button 75 | position absolute 76 | width 24px 77 | height 24px 78 | top 8px 79 | left 12px 80 | background url(../images/menu.png) center center no-repeat 81 | background-size 24px 82 | .logo 83 | position absolute 84 | width 30px 85 | height 30px 86 | background url(../images/logo.png) center center no-repeat 87 | top 5px 88 | left 50% 89 | margin-left -15px 90 | background-size 30px 91 | 92 | .sidebar 93 | position absolute 94 | z-index 10 95 | top 0 96 | left 60px 97 | bottom 0 98 | padding 2.2em 0 99 | width 260px 100 | margin-right 20px 101 | overflow-x hidden 102 | overflow-y auto 103 | -webkit-overflow-scrolling touch 104 | -ms-overflow-style none 105 | h2 106 | margin-top .2em 107 | ul 108 | list-style-type none 109 | margin 0 110 | line-height 1.8em 111 | padding-left 1em 112 | .version-select 113 | vertical-align middle 114 | margin-left 5px 115 | .menu-root 116 | padding-left 0 117 | .menu-sub 118 | font-size .85em 119 | .sidebar-link 120 | color $light 121 | &.current 122 | font-weight 600 123 | color $green 124 | &.new 125 | &:after 126 | content "NEW" 127 | display inline-block 128 | font-size 10px 129 | font-weight 600 130 | color #fff 131 | background-color $green 132 | line-height 14px 133 | padding 0 4px 134 | border-radius 3px 135 | margin-left 5px 136 | vertical-align middle 137 | position relative 138 | top -1px 139 | &:hover 140 | border-bottom 2px solid $green 141 | .section-link 142 | &.active 143 | font-weight bold 144 | color $green 145 | .main-menu 146 | margin-bottom 20px 147 | display none 148 | padding-left 0 149 | 150 | .content 151 | padding 2.2em 0 152 | max-width 600px 153 | margin 0 auto 154 | &.api 155 | ul 156 | padding-left 1.25em 157 | line-height 1.4em 158 | ul, p 159 | margin .6em 0 160 | a.button 161 | font-size .9em 162 | color #fff 163 | margin .2em 0 164 | width 180px 165 | text-align center 166 | padding 12px 24px 167 | display inline-block 168 | vertical-align middle 169 | img 170 | max-width 100% 171 | span.light 172 | color $light 173 | span.info 174 | font-size .85em 175 | display inline-block 176 | vertical-align middle 177 | width 280px 178 | margin-left 20px 179 | h1 180 | margin 0 0 1em 181 | h2 182 | margin 2em 0 .8em 183 | padding-bottom .7em 184 | border-bottom 1px solid $border 185 | h3 186 | margin 3em 0 1.2em 187 | position relative 188 | &:before 189 | content "#" 190 | color $green 191 | position absolute 192 | left -0.7em 193 | top -2px 194 | font-size 1.2em 195 | font-weight bold 196 | figure, p, ul, ol 197 | margin 1.2em 0 198 | p, ul, ol 199 | line-height 1.6em 200 | ul, ol 201 | padding-left 1.5em 202 | a 203 | color $green 204 | font-weight 600 205 | blockquote 206 | margin 2em 0 207 | padding-left 20px 208 | border-left 4px solid $green 209 | p 210 | font-weight 600 211 | margin-left 0 212 | iframe 213 | margin 1em 0 214 | p.tip 215 | padding 12px 24px 12px 30px 216 | margin 2em 0 217 | border-left 4px solid $red 218 | background-color $codebg 219 | position relative 220 | border-bottom-right-radius $radius 221 | border-top-right-radius $radius 222 | &:before 223 | position absolute 224 | top 14px 225 | left -12px 226 | background-color $red 227 | color #fff 228 | content "!" 229 | width 20px 230 | height 20px 231 | border-radius 100% 232 | text-align center 233 | line-height 20px 234 | font-weight bold 235 | font-family $logo-font 236 | font-size 14px 237 | 238 | .guide-links 239 | margin-top 2em 240 | height 1em 241 | 242 | .footer 243 | color $light 244 | margin-top 2em 245 | padding-top 2em 246 | border-top 1px solid #e5e5e5 247 | font-size .9em 248 | 249 | #main.fix-sidebar 250 | .sidebar 251 | position fixed 252 | 253 | #donate 254 | margin-top 15px 255 | 256 | @media screen and (max-width: 1300px) 257 | .content.with-sidebar 258 | margin-left 290px 259 | #ad 260 | z-index 8 261 | position relative 262 | width 140px 263 | height 60px 264 | padding 0 265 | bottom 0 266 | right 0 267 | margin 0 0 15px -6px 268 | .carbon-wrap, .carbon-img, .carbon-text, .carbon-poweredby 269 | display inline-block 270 | vertical-align top 271 | .carbon-text 272 | width 130px 273 | margin-left 15px 274 | .carbon-poweredby 275 | position absolute 276 | bottom 0 277 | left 145px 278 | 279 | @media screen and (max-width: 720px) 280 | #ad 281 | width 100% 282 | body 283 | -webkit-text-size-adjust none 284 | font-size 14px 285 | #header 286 | display none 287 | #logo 288 | display none 289 | .nav-link 290 | padding-bottom 1px 291 | &:hover, &.current 292 | border-bottom 2px solid $green 293 | #search-query 294 | width 200px 295 | margin-bottom 10px 296 | #mobile-bar 297 | display block 298 | #main 299 | padding 2em 1.4em 0 300 | .highlight pre 301 | padding 1.2em 1em 302 | .sidebar 303 | position fixed 304 | background-color #f9f9f9 305 | height 100% 306 | top 0 307 | left 0 308 | padding 60px 30px 20px 309 | box-shadow 0 0 10px rgba(0,0,0,.2) 310 | box-sizing border-box 311 | transition all .4s cubic-bezier(0.4, 0, 0, 1) 312 | -webkit-transform translate(-280px, 0) 313 | transform translate(-280px, 0) 314 | .main-menu 315 | display block 316 | &.open 317 | -webkit-transform translate(0, 0) 318 | transform translate(0, 0) 319 | .content 320 | &.with-sidebar 321 | margin-left 0 322 | .footer 323 | margin-left 0 324 | text-align center 325 | 326 | @media screen and (max-width: 560px) 327 | #downloads 328 | text-align center 329 | margin-bottom 25px 330 | .info 331 | margin-top 5px 332 | margin-left 0 333 | iframe 334 | margin: 0 !important 335 | -------------------------------------------------------------------------------- /src/guide/reactivity.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reactivity in Depth 3 | type: guide 4 | order: 13 5 | --- 6 | 7 | We've covered most of the basics - now it's time to take a deep dive! One of Vue.js' most distinct features is the unobtrusive reactive system - models are just plain JavaScript objects, modify it and the view updates. It makes state management very simple and intuitive, but it's also important to understand how it works to avoid some common gotchas. In this section, we are going to dig into some of the lower-level details of Vue.js' reactivity system. 8 | 9 | ## How Changes Are Tracked 10 | 11 | When you pass a plain JavaScript object to a Vue instance as its `data` option, Vue.js will walk through all of its properties and convert them to getter/setters using [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty). This is an ES5-only and un-shimmable feature, which is why Vue.js doesn't support IE8 and below. 12 | 13 | The getter/setters are invisible to the user, but under the hood they enable Vue.js to perform dependency-tracking and change-notification when properties are accessed or modified. One caveat is that browser consoles format getter/setters differently when converted data objects are logged, so make sure to use the `vm.$log()` instance method for more inspection-friendly output. 14 | 15 | For every directive / data binding in the template, there will be a corresponding **watcher** object, which records any properties "touched" during its evaluation as dependencies. Later on when a dependency's setter is called, it triggers the watcher to re-evaluate, and in turn causes its associated directive to perform DOM updates. 16 | 17 | ![data](/images/data.png) 18 | 19 | ## Change Detection Caveats 20 | 21 | Due to the limitation of ES5, Vue.js **cannot detect property addition or deletion**. Since Vue.js performs the getter/setter conversion process during instance initialization, a property must be present in the `data` object in order for Vue.js to convert it and make it reactive. For example: 22 | 23 | ``` js 24 | var data = { a: 1 } 25 | var vm = new Vue({ 26 | data: data 27 | }) 28 | // `vm.a` and `data.a` are now reactive 29 | 30 | vm.b = 2 31 | // `vm.b` is NOT reactive 32 | 33 | data.b = 2 34 | // `data.b` is NOT reactive 35 | ``` 36 | 37 | However, there are ways to **add a property and make it reactive** after an instance has been created. 38 | 39 | For Vue instances, you can use the `$set(path, value)` instance method: 40 | 41 | ``` js 42 | vm.$set('b', 2) 43 | // `vm.b` and `data.b` are now reactive 44 | ``` 45 | 46 | For plain data objects, you can use the global `Vue.set(object, key, value)` method: 47 | 48 | ``` js 49 | Vue.set(data, 'c', 3) 50 | // `vm.c` and `data.c` are now reactive 51 | ``` 52 | 53 | Sometimes you may want to assign a number of properties on to an existing object, for example using `Object.assign()` or `_.extend()`. However, new properties added to the object will not trigger changes. In such cases, create a fresh object with properties from both the original object and the mixin object: 54 | 55 | ``` js 56 | // instead of `Object.assign(this.someObject, { a: 1, b: 2 })` 57 | this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 }) 58 | ``` 59 | 60 | There are also a few Array-related caveats, which were [discussed earlier in the list rendering section](/guide/list.html#Caveats). 61 | 62 | ## Initialize Your Data 63 | 64 | Although Vue.js provides the API to dynamically add reactive properties on the fly, it is recommended to declare all reactive properties upfront in the `data` option. 65 | 66 | Instead of this: 67 | 68 | ``` js 69 | var vm = new Vue({ 70 | template: '
    {{msg}}
    ' 71 | }) 72 | // add `msg` later 73 | vm.$set('msg', 'Hello!') 74 | ``` 75 | 76 | Prefer this: 77 | 78 | ``` js 79 | var vm = new Vue({ 80 | data: { 81 | // declare msg with an empty value 82 | msg: '' 83 | }, 84 | template: '
    {{msg}}
    ' 85 | }) 86 | // set `msg` later 87 | vm.msg = 'Hello!' 88 | ``` 89 | 90 | There are two reasons behind this pattern: 91 | 92 | 1. The `data` object is like the schema for your component's state. Declaring all reactive properties upfront makes the component code easier to understand and reason about. 93 | 94 | 2. Adding a top level reactive property on a Vue instance will force all the watchers in its scope to re-evaluate, because it didn't exist before and no watcher could have tracked it as a dependency. The performance is usually acceptable (essentially the same as Angular's dirty checking), but can be avoided when you initialize the data properly. 95 | 96 | ## Async Update Queue 97 | 98 | By default, Vue.js performs DOM updates **asynchronously**. Whenever a data change is observed, Vue will open a queue and buffer all the data changes that happens in the same event loop. If the same watcher is triggered multiple times, it will be pushed into the queue only once. Then, in the next event loop "tick", Vue flushes the queue and performs only the necessary DOM updates. Internally Vue uses `MutationObserver` if available for the asynchronous queuing and falls back to `setTimeout(fn, 0)`. 99 | 100 | For example, when you set `vm.someData = 'new value'`, the DOM will not update immediately. It will update in the next "tick", when the queue is flushed. Most of the time we don't need to care about this, but it can be tricky when you want to do something that depends on the post-update DOM state. Although Vue.js generally encourages developers to think in a "data-driven" fashion and avoid touching the DOM directly, sometimes it might be necessary to get your hands dirty. In order to wait until Vue.js has finished updating the DOM after a data change, you can use `Vue.nextTick(callback)` immediately after the data is changed. The callback will be called after the DOM has been updated. For example: 101 | 102 | ``` html 103 |
    {{msg}}
    104 | ``` 105 | 106 | ``` js 107 | var vm = new Vue({ 108 | el: '#example', 109 | data: { 110 | msg: '123' 111 | } 112 | }) 113 | vm.msg = 'new message' // change data 114 | vm.$el.textContent === 'new message' // false 115 | Vue.nextTick(function () { 116 | vm.$el.textContent === 'new message' // true 117 | }) 118 | ``` 119 | 120 | There is also the `vm.$nextTick()` instance method, which is especially handy inside components, because it doesn't need global `Vue` and its callback's `this` context will be automatically bound to the current Vue instance: 121 | 122 | ``` js 123 | Vue.component('example', { 124 | template: '{{msg}}', 125 | data: function () { 126 | return { 127 | msg: 'not updated' 128 | } 129 | }, 130 | methods: { 131 | updateMessage: function () { 132 | this.msg = 'updated' 133 | console.log(this.$el.textContent) // => 'not updated' 134 | this.$nextTick(function () { 135 | console.log(this.$el.textContent) // => 'updated' 136 | }) 137 | } 138 | } 139 | }) 140 | ``` 141 | 142 | ## Inside Computed Properties 143 | 144 | It should be noted that Vue.js computed properties are **not** simple getters. Each computed property keeps track of its own reactive dependencies. When a computed property is evaluated, Vue.js updates its dependency list and caches the result value. The cached value is only invalidated when one of the tracked dependencies have changed. Therefore, as long as the dependencies did not change, accessing the computed property will directly return the cached value instead of calling the getter. 145 | 146 | Why do we need caching? Imagine we have an expensive computed property **A**, which requires looping through a huge Array and doing a lot of computations. Then, we may have other computed properties that in turn depend on **A**. Without caching, we would be calling **A**’s getter many more times than necessary! 147 | 148 | Because of computed property caching, the getter function is not always called when you access a computed property. Consider the following example: 149 | 150 | ``` js 151 | var vm = new Vue({ 152 | data: { 153 | msg: 'hi' 154 | }, 155 | computed: { 156 | example: function () { 157 | return Date.now() + this.msg 158 | } 159 | } 160 | }) 161 | ``` 162 | 163 | The computed property `example` has only one dependency: `vm.msg`. `Date.now()` is **not** a reactive dependency, because it has nothing to do with Vue's data observation system. Therefore, when you programmatically access `vm.example`, you will find the timestamp to remain the same unless `vm.msg` triggers a re-evaluation. 164 | 165 | In some use cases you may want to preserve the simple getter-like behavior, where every time you access `vm.example` it simply calls the getter again. You can do that by turning off caching for a specific computed property: 166 | 167 | ``` js 168 | computed: { 169 | example: { 170 | cache: false, 171 | get: function () { 172 | return Date.now() + this.msg 173 | } 174 | } 175 | } 176 | ``` 177 | 178 | Now, every time you access `vm.example`, the timestamp will be up-to-date. **However, note this only affects programmatic access inside JavaScript; data-bindings are still dependency-driven.** When you bind to a computed property in the template as `{% raw %}{{example}}{% endraw %}`, the DOM will only be updated when a reactive dependency has changed. 179 | -------------------------------------------------------------------------------- /themes/vue/source/css/index.styl: -------------------------------------------------------------------------------- 1 | @import "_common" 2 | 3 | zoom() 4 | -webkit-transform scale(1.05) 5 | -moz-transform scale(1.05) 6 | -ms-transform scale(1.05) 7 | transform scale(1.05) 8 | 9 | html, body 10 | height 100% 11 | 12 | #nav, #translations 13 | list-style-type none 14 | text-align center 15 | padding 0 16 | margin 0 17 | li 18 | display inline-block 19 | position relative 20 | line-height 40px 21 | &:last-child .nav-link 22 | margin-right 0 23 | 24 | #translations 25 | position fixed 26 | right 1em 27 | bottom 0.5em 28 | .delimiter 29 | color $light 30 | margin 0 5px 31 | .nav-link 32 | margin 0 33 | 34 | .nav-link 35 | color $light 36 | padding-bottom 3px 37 | margin 0 1.5em 38 | &:first-child 39 | margin-left 0 40 | &:hover, &.current 41 | border-bottom 3px solid $green 42 | 43 | #logo 44 | display block 45 | margin 0 auto 46 | width 200px 47 | 48 | #logo-wrap 49 | margin 3.5em 0 4em 50 | 51 | #hero 52 | text-align center 53 | height 100% 54 | min-height 720px 55 | position relative 56 | .inner 57 | z-index 2 58 | height 640px 59 | width 100% 60 | position absolute 61 | top 50% 62 | margin-top -340px 63 | left 0 64 | h1 65 | font-family $logo-font 66 | font-weight 300 67 | font-size 4em 68 | margin 0 69 | .warning 70 | color $light 71 | .desc 72 | max-width 800px 73 | padding 0 20px 74 | text-align center 75 | margin 1.5em auto 76 | color $light 77 | .down 78 | position absolute 79 | z-index 1 80 | bottom 0 81 | width 100% 82 | left 0 83 | padding 1.5em 0 84 | img 85 | width 20px 86 | a.button 87 | width 280px 88 | margin .5em 89 | 90 | #social 91 | text-align center 92 | list-style-type none 93 | margin 0 auto 94 | padding 0 95 | margin 1.5em auto 96 | li 97 | display inline-block 98 | margin 0 5px 99 | vertical-align middle 100 | &.last 101 | margin-left -2px 102 | 103 | #example 104 | //background-color #f3f3f3 105 | text-align center 106 | padding 20px 107 | max-width 1200px 108 | margin 0 auto 3em 109 | h2 110 | margin-bottom 1.5em 111 | code, pre 112 | background-color transparent 113 | figure.highlight 114 | margin 0 115 | box-shadow none 116 | background-color transparent 117 | .sign 118 | display inline-block 119 | height 10em 120 | line-height 9em 121 | padding 0 .5em 122 | font-weight 600 123 | color $light 124 | .block 125 | text-align left 126 | display inline-block 127 | width 28% 128 | height 10em 129 | vertical-align top 130 | background-color #f9f9f9 131 | border-radius 2px 132 | box-shadow 0 1px 2px rgba(0,0,0,.125) 133 | #demo 134 | padding 0 20px 135 | word-wrap break-word 136 | input 137 | font-size .75em 138 | border 1px solid #ccc 139 | padding 4px 8px 140 | border-radius 2px 141 | font-family $body-font 142 | &:focus 143 | outline none 144 | border-color $green 145 | 146 | #features 147 | padding 3em 0 148 | text-align center 149 | background-color #f9f9f9 150 | .cool 151 | font-size 1.8em 152 | text-align center 153 | margin-top 1em 154 | color $light 155 | .feats 156 | max-width 1200px 157 | margin 0 auto 158 | .feat 159 | box-sizing border-box 160 | -moz-box-sizing border-box 161 | display inline-block 162 | text-align left 163 | vertical-align top 164 | width 280px 165 | margin 40px 166 | h2 167 | color $medium 168 | line-height 40px 169 | margin-bottom 0 170 | p 171 | color $light 172 | padding-left 52px 173 | margin .4em 0 174 | a 175 | color $green 176 | font-weight 600 177 | .icon 178 | display inline-block 179 | vertical-align middle 180 | position relative 181 | top -3px 182 | width 40px 183 | height 40px 184 | margin-right 12px 185 | background url(../images/icons.png) 186 | background-size 240px 40px 187 | &.fast 188 | background-position -40px 0 189 | &.compact 190 | background-position -80px 0 191 | &.powerful 192 | background-position -120px 0 193 | &.composable 194 | background-position -160px 0 195 | &.module 196 | background-position -200px 0 197 | 198 | #why 199 | padding 4em 0 200 | background-color $green 201 | color #fff 202 | h2 203 | margin-top 0 204 | color #fff 205 | font-size 1.5em 206 | text-align center 207 | ul 208 | line-height 1.8em 209 | font-size 1.15em 210 | width 320px 211 | margin 0 auto 212 | padding 0 213 | list-style-type none 214 | li:before 215 | content "" 216 | display inline-block 217 | width 24px 218 | height 24px 219 | background url(../images/check.png) center center no-repeat 220 | background-size 24px 24px 221 | margin-right 10px 222 | position relative 223 | top 4px 224 | 225 | #footer 226 | text-align center 227 | color #fff 228 | padding 4em 0 229 | background-color #7f8c8d 230 | .avatar 231 | width 100px 232 | border-radius 100% 233 | margin 2.5em 0 1em 234 | a 235 | color #fff 236 | text-decoration underline 237 | &.start 238 | font-size 1.2em 239 | text-decoration none 240 | text-transform uppercase 241 | letter-spacing 1px 242 | border 1px solid #fff 243 | display inline-block 244 | padding 12px 20px 245 | border-radius 25px 246 | transition all .15s ease 247 | margin-bottom 2em 248 | &:hover 249 | background-color #fff 250 | color #7f8c8d 251 | zoom() 252 | p 253 | margin .3em 0 254 | 255 | #main 256 | display none 257 | 258 | #donate 259 | margin-left -2px !important 260 | 261 | #sponsors 262 | padding-top 20px 263 | 264 | #sponsors, #sponsors-mobile 265 | span 266 | color $light 267 | font-size .85em 268 | a, img 269 | position relative 270 | width 100px 271 | display inline-block 272 | vertical-align middle 273 | a 274 | margin 5px 10px 0 275 | 276 | #sponsors-mobile 277 | display none 278 | text-align center 279 | margin-bottom 2em 280 | padding 0 1em 281 | a 282 | margin 20px 10px 0 283 | 284 | @media screen and (max-width: 480px) 285 | body 286 | font-size 14px 287 | #nav 288 | margin 1.5em 1.2em 0 289 | #translations 290 | margin-bottom 2em 291 | #logo 292 | width 120px 293 | .nav-link 294 | font-size .85em 295 | margin 0 .5em 296 | .divider 297 | font-size 1.2em 298 | margin 2.5em 1em 299 | #hero 300 | min-height 560px 301 | .inner 302 | height 600px 303 | margin-top -300px 304 | h1 305 | font-size 2em 306 | font-weight 400 307 | .buttons 308 | max-width 300px 309 | margin 1em auto 310 | a.button 311 | width 260px 312 | font-size .8em 313 | margin .5em 0 314 | a.small-button 315 | margin .3em 0 316 | .desc 317 | max-width 300px 318 | .warning, .desc 319 | font-size .85em 320 | margin .8em auto 321 | br 322 | display none 323 | .down 324 | display none 325 | #social 326 | max-width 340px 327 | margin 1.2em auto 328 | line-height 1.8em 329 | .cool 330 | margin-top 0 331 | #features .feat 332 | font-size 14px 333 | margin .8em 0 334 | width 250px 335 | #why 336 | ul 337 | width 280px 338 | font-size 1.1em 339 | h2 340 | font-size 1.4em 341 | 342 | @media screen and (max-width: 960px) 343 | #features, #hero 344 | font-size 16px 345 | #sponsors 346 | display none 347 | #sponsors-mobile 348 | display block 349 | #example 350 | .block 351 | display block 352 | width auto 353 | height auto 354 | #demo 355 | padding 5px 20px 20px 356 | .sign 357 | display block 358 | height 1em 359 | line-height 1em 360 | padding .5em 0 361 | #translations 362 | position relative 363 | right 0 364 | bottom 0 365 | -------------------------------------------------------------------------------- /src/guide/comparison.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Comparison with Other Frameworks 3 | type: guide 4 | order: 19 5 | --- 6 | 7 | ## Angular 8 | 9 | There are a few reasons to use Vue over Angular, although they might not apply for everyone: 10 | 11 | - Vue.js is much simpler than Angular, both in terms of API and design. You can learn nearly everything about it quickly and become productive. 12 | 13 | - Vue.js is a more flexible, less opinionated solution. That allows you to structure your app the way you want it to be, instead of being forced to do everything the Angular way. It's only an interface layer so you can use it as a light feature in pages instead of a full blown SPA. It gives you bigger room to mix and match with other libraries, but you are also responsible for making more architectural decisions. For example, Vue.js' core doesn't come with routing or ajax functionalities by default, and usually assumes you are building the application using an external module bundler. This is probably the most important distinction. 14 | 15 | - Angular uses two-way binding between scopes. While Vue also supports explicit two-way bindings, it defaults to a one-way, parent-to-child data flow between components. Using one-way binding makes the flow of data easier to reason about in large apps. 16 | 17 | - Vue.js has a clearer separation between directives and components. Directives are meant to encapsulate DOM manipulations only, while Components stand for a self-contained unit that has its own view and data logic. In Angular there's a lot of confusion between the two. 18 | 19 | - Vue.js has better performance and is much, much easier to optimize, because it doesn't use dirty checking. Angular gets slow when there are a lot of watchers, because every time anything in the scope changes, all these watchers need to be re-evaluated again. Also, the digest cycle may have to run multiple times to "stabilize" if some watcher triggers another update. Angular users often have to resort to esoteric techniques to get around the digest cycle, and in some situations there's simply no way to optimize a scope with a large amount of watchers. Vue.js doesn't suffer from this at all because it uses a transparent dependency-tracking observing system with async queueing - all changes trigger independently unless they have explicit dependency relationships. The only optimization hint you'll ever need is the `track-by` param on `v-for` lists. 20 | 21 | Interestingly, there are quite some similarities in how Angular 2 and Vue are addressing these Angular 1 issues. 22 | 23 | ## React 24 | 25 | React and Vue.js do share a similarity in that they both provide reactive & composable View components. There are, of course, many differences as well. 26 | 27 | First, the internal implementation is fundamentally different. React's rendering leverages the Virtual DOM - an in-memory representation of what the actual DOM should look like. When the state changes, React does a full re-render of the Virtual DOM, diffs it, and then patches the real DOM. 28 | 29 | The virtual-DOM approach provides a functional way to describe your view at any point of time, which is really nice. Because it doesn't use observables and re-renders the entire app on every update, the view is by definition guaranteed to be in sync with the data. It also opens up possibilities to isomorphic JavaScript applications. 30 | 31 | Instead of a Virtual DOM, Vue.js uses the actual DOM as the template and keeps references to actual nodes for data bindings. This limits Vue.js to environments where DOM is present. However, contrary to the common misconception that Virtual-DOM makes React faster than anything else, Vue.js actually out-performs React when it comes to hot updates, and requires almost no hand-tuned optimization. With React, you need to implement `shouldComponentUpdate` everywhere and use immutable data structures to achieve fully optimized re-renders. 32 | 33 | API-wise, one issue with React (or JSX) is that the render function often involves a lot of logic, and ends up looking more like a piece of program (which in fact it is) rather than a visual representation of the interface. For some developers this is a bonus, but for designer/developer hybrids like me, having a template makes it much easier to think visually about the design and CSS. JSX mixed with JavaScript logic breaks that visual model I need to map the code to the design. In contrast, Vue.js pays the cost of a lightweight data-binding DSL so that we have a visually scannable template and with logic encapsulated into directives and filters. 34 | 35 | Another issue with React is that because DOM updates are completely delegated to the Virtual DOM, it's a bit tricky when you actually **want** to control the DOM yourself (although theoretically you can, you'd be essentially working against the library when you do that). For applications that need ad-hoc custom DOM manipulations, especially animations with complex timing requirements, this can become a pretty annoying restriction. On this front, Vue.js allows for more flexibility and there are [multiple FWA/Awwwards winning sites](https://github.com/vuejs/awesome-vue#interactive-experiences) built with Vue.js. 36 | 37 | Some additional notes: 38 | 39 | - The React team has very ambitious goals in making React a platform-agnostic UI development paradigm, while Vue is focused on providing a pragmatic solution for the web. 40 | 41 | - React, due to its functional nature, plays very well with functional programming patterns. However it also introduces a higher learning barrier for junior developers and beginners. Vue is much easier to pick up and get productive with in this regard. 42 | 43 | - For large applications, the React community has been doing a lot of innovation in terms of state management solutions, e.g. Flux/Redux. Vue itself doesn't really address that problem (same for React core), but the state management patterns can be easily adopted for a similar architecture. Vue has its own state management solution called [Vuex](https://github.com/vuejs/vuex), and it's also possible to [use Redux with Vue](https://github.com/egoist/revue). 44 | 45 | - The trend in React development is pushing you to put everything in JavaScript, including your CSS. There has been many CSS-in-JS solutions out there but all more or less have its own problems. And most importantly, it deviates from the standard CSS authoring experience and makes it very awkward to leverage existing work in the CSS community. Vue's [single file components](/guide/application.html#Single-File-Components) gives you component-encapsulated CSS while still allowing you to use your pre-processors of choice. 46 | 47 | ## Ember 48 | 49 | Ember is a full-featured framework that is designed to be highly opinionated. It provides a lot of established conventions, and once you are familiar enough with them, it can make you very productive. However, it also means the learning curve is high and the flexibility suffers. It's a trade-off when you try to pick between an opinionated framework and a library with a loosely coupled set of tools that work together. The latter gives you more freedom but also requires you to make more architectural decisions. 50 | 51 | That said, it would probably make a better comparison between Vue.js core and Ember's templating and object model layer: 52 | 53 | - Vue provides unobtrusive reactivity on plain JavaScript objects, and fully automatic computed properties. In Ember you need to wrap everything in Ember Objects and manually declare dependencies for computed properties. 54 | 55 | - Vue's template syntax harnesses the full power of JavaScript expressions, while Handlebars' expression and helper syntax is quite limited in comparison. 56 | 57 | - Performance wise, Vue outperforms Ember by a fair margin, even after the latest Glimmer engine update in Ember 2.0. Vue automatically batches updates, while in Ember you need to manually manage run loops in performance-critical situations. 58 | 59 | ## Polymer 60 | 61 | Polymer is yet another Google-sponsored project and in fact was a source of inspiration for Vue.js as well. Vue.js' components can be loosely compared to Polymer's custom elements, and both provide a very similar development style. The biggest difference is that Polymer is built upon the latest Web Components features, and requires non-trivial polyfills to work (with degraded performance) in browsers that don't support those features natively. In contrast, Vue.js works without any dependencies down to IE9. 62 | 63 | Also, in Polymer 1.0 the team has really made its data-binding system very limited in order to compensate for the performance. For example, the only expressions supported in Polymer templates are the boolean negation and single method calls. Its computed property implementation is also not very flexible. 64 | 65 | Finally, when deploying to production, Polymer elements need to be bundled via a Polymer-specific tool called vulcanizer. In comparison, single file Vue components can leverage everything the Webpack ecosystem has to offer, and thus you can easily use ES6 and any CSS pre-processors you want in your Vue components. 66 | 67 | ## Riot 68 | 69 | Riot 2.0 provides a similar component-based development model (which is called a "tag" in Riot), with a minimal and beautifully designed API. I think Riot and Vue share a lot in design philosophies. However, despite being a bit heavier than Riot, Vue does offer some significant advantages over Riot: 70 | 71 | - True conditional rendering (Riot renders all if branches and simply show/hide them) 72 | - A far-more powerful router (Riot’s routing API is just way too minimal) 73 | - More mature tooling support (see webpack + vue-loader) 74 | - Transition effect system (Riot has none) 75 | - Better performance. (Riot in fact uses dirty checking rather than a virtual-dom, and thus suffers from the same performance issues as Angular.) 76 | --------------------------------------------------------------------------------