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 |
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 |
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 |
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 |
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 |
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 |
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 |
151 |
Data binding yang Extendable
152 |
Object models Javascript biasa
153 |
API yang mudah dimengerti
154 |
Membangun UI dengan cara menyusun komponen-komponen
155 |
Mixing & matching library kecil
156 |
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 | 
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 | 
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 |
--------------------------------------------------------------------------------