Skip to content

Commit ab4fac3

Browse files
Rewrite of instance.md, introducing data-methods.md (#514)
* docs: experimental rewrite of instance.md, introducing data-methods.md * docs: cut material from instance.md that isn't on topic * docs: move data-methods.md to after template-syntax.md * fix: change 'application' to 'component' in template-syntax.md * fix: use bold when introducing new terms in instance.md * docs: rewrite data-methods.md
1 parent 2865878 commit ab4fac3

File tree

4 files changed

+180
-93
lines changed

4 files changed

+180
-93
lines changed

src/.vuepress/config.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const sidebar = {
1515
'/guide/introduction',
1616
'/guide/instance',
1717
'/guide/template-syntax',
18+
'/guide/data-methods',
1819
'/guide/computed',
1920
'/guide/class-and-style',
2021
'/guide/conditional',

src/guide/data-methods.md

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Data Properties and Methods
2+
3+
## Data Properties
4+
5+
The `data` option for a component is a function. Vue calls this function as part of creating a new component instance. It should return an object, which Vue will then wrap in its reactivity system and store on the component instance as `$data`. For convenience, any top-level properties of that object are also exposed directly via the component instance:
6+
7+
```js
8+
const app = Vue.createApp({
9+
data() {
10+
return { count: 4 }
11+
}
12+
})
13+
14+
const vm = app.mount('#app')
15+
16+
console.log(vm.$data.count) // => 4
17+
console.log(vm.count) // => 4
18+
19+
// Assigning a value to vm.count will also update $data.count
20+
vm.count = 5
21+
console.log(vm.$data.count) // => 5
22+
23+
// ... and vice-versa
24+
vm.$data.count = 6
25+
console.log(vm.count) // => 6
26+
```
27+
28+
These instance properties are only added when the instance is first created, so you need to ensure they are all present in the object returned by the `data` function. Where necessary, use `null`, `undefined` or some other placeholder value for properties where the desired value isn't yet available.
29+
30+
It is possible to add a new property directly to the component instance without including it in `data`. However, because this property isn't backed by the reactive `$data` object, it won't automatically be tracked by [Vue's reactivity system](reactivity.html).
31+
32+
Vue uses a `$` prefix when exposing its own built-in APIs via the component instance. It also reserves the prefix `_` for internal properties. You should avoid using names for top-level `data` properties that start with either of these characters.
33+
34+
## Methods
35+
36+
To add methods to a component instance we use the `methods` option. This should be an object containing the desired methods:
37+
38+
```js
39+
const app = Vue.createApp({
40+
data() {
41+
return { count: 4 }
42+
},
43+
methods: {
44+
increment() {
45+
// `this` will refer to the component instance
46+
this.count++
47+
}
48+
}
49+
})
50+
51+
const vm = app.mount('#app')
52+
53+
console.log(vm.count) // => 4
54+
55+
vm.increment()
56+
57+
console.log(vm.count) // => 5
58+
```
59+
60+
Vue automatically binds the `this` value for `methods` so that it always refers to the component instance. This ensures that a method retains the correct `this` value if it's used as an event listener or callback. You should avoid using arrow functions when defining `methods`, as that prevents Vue from binding the appropriate `this` value.
61+
62+
Just like all other properties of the component instance, the `methods` are accessible from within the component's template. Inside a template they are most commonly used as event listeners:
63+
64+
```html
65+
<button @click="increment">Up vote</button>
66+
```
67+
68+
In the example above, the method `increment` will be called when the `<button>` is clicked.
69+
70+
It is also possible to call a method directly from a template. As we'll see shortly, it's usually better to use a [computed property](computed.html) instead. However, using a method can be useful in scenarios where computed properties aren't a viable option. You can call a method anywhere that a template supports JavaScript expressions:
71+
72+
```html
73+
<span :title="toTitleDate(date)">
74+
{{ formatDate(date) }}
75+
</span>
76+
```
77+
78+
If the methods `toTitleDate` or `formatDate` access any reactive data then it will be tracked as a rendering dependency, just as if it had been used in the template directly.
79+
80+
Methods called from a template should not have any side effects, such as changing data or triggering asynchronous processes. If you find yourself tempted to do that you should probably use a [lifecycle hook](instance.html#lifecycle-hooks) instead.
81+
82+
### Debouncing and Throttling
83+
84+
Vue doesn't include built-in support for debouncing or throttling but it can be implemented using libraries such as [Lodash](https://lodash.com/).
85+
86+
In cases where a component is only used once, the debouncing can be applied directly within `methods`:
87+
88+
```html
89+
<script src="https://unpkg.com/[email protected]/lodash.min.js"></script>
90+
<script>
91+
Vue.createApp({
92+
methods: {
93+
// Debouncing with Lodash
94+
click: _.debounce(function() {
95+
// ... respond to click ...
96+
}, 500)
97+
}
98+
}).mount('#app')
99+
</script>
100+
```
101+
102+
However, this approach is potentially problematic for components that are reused because they'll all share the same debounced function. To keep the component instances independent from each other, we can add the debounced function in the `created` lifecycle hook:
103+
104+
```js
105+
app.component('save-button', {
106+
created() {
107+
// Debouncing with Lodash
108+
this.debouncedClick = _.debounce(this.click, 500)
109+
},
110+
unmounted() {
111+
// Cancel the timer when the component is removed
112+
this.debouncedClick.cancel()
113+
},
114+
methods: {
115+
click() {
116+
// ... respond to click ...
117+
}
118+
},
119+
template: `
120+
<button @click="debouncedClick">
121+
Save
122+
</button>
123+
`
124+
})
125+
```

src/guide/instance.md

+51-90
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,100 @@
1-
# The Application Instance
1+
# Application & Component Instances
22

3-
## Creating an Instance
3+
## Creating an Application Instance
44

55
Every Vue application starts by creating a new **application instance** with the `createApp` function:
66

77
```js
8-
Vue.createApp(/* options */)
8+
const app = Vue.createApp({ /* options */ })
99
```
1010

11-
After the instance is created, we can _mount_ it, passing a container to `mount` method. For example, if we want to mount a Vue application on `<div id="app"></div>`, we should pass `#app`:
11+
The application instance is used to register 'globals' that can then be used by components within that application. We'll discuss that in detail later in the guide but as a quick example:
1212

1313
```js
14-
Vue.createApp(/* options */).mount('#app')
14+
const app = Vue.createApp({})
15+
app.component('SearchInput', SearchInputComponent)
16+
app.directive('focus', FocusDirective)
17+
app.use(LocalePlugin)
1518
```
1619

17-
Although not strictly associated with the [MVVM pattern](https://en.wikipedia.org/wiki/Model_View_ViewModel), Vue's design was partly inspired by it. As a convention, we often use the variable `vm` (short for ViewModel) to refer to our instance.
18-
19-
When you create an instance, you pass in an **options object**. The majority of this guide describes how you can use these options to create your desired behavior. For reference, you can also browse the full list of options in the [API reference](../api/options-data.html).
20-
21-
A Vue application consists of a **root instance** created with `createApp`, optionally organized into a tree of nested, reusable components. For example, a `todo` app's component tree might look like this:
22-
23-
```
24-
Root Instance
25-
└─ TodoList
26-
├─ TodoItem
27-
│ ├─ DeleteTodoButton
28-
│ └─ EditTodoButton
29-
└─ TodoListFooter
30-
├─ ClearTodosButton
31-
└─ TodoListStatistics
32-
```
33-
34-
We'll talk about [the component system](component-basics.html) in detail later. For now, just know that all Vue components are also instances, and so accept the same options object.
35-
36-
## Data and Methods
37-
38-
When an instance is created, it adds all the properties found in its `data` to [Vue's **reactivity system**](reactivity.html). When the values of those properties change, the view will "react", updating to match the new values.
20+
Most of the methods exposed by the application instance return that same instance, allowing for chaining:
3921

4022
```js
41-
// Our data object
42-
const data = { a: 1 }
23+
Vue.createApp({})
24+
.component('SearchInput', SearchInputComponent)
25+
.directive('focus', FocusDirective)
26+
.use(LocalePlugin)
27+
```
4328

44-
// The object is added to the root instance
45-
const vm = Vue.createApp({
46-
data() {
47-
return data
48-
}
49-
}).mount('#app')
29+
You can browse the full application API in the [API reference](../api/application-api.html).
5030

51-
// Getting the property on the instance
52-
// returns the one from the original data
53-
vm.a === data.a // => true
31+
## The Root Component
5432

55-
// Setting the property on the instance
56-
// also affects the original data
57-
vm.a = 2
58-
data.a // => 2
59-
```
33+
The options passed to `createApp` are used to configure the **root component**. That component is used as the starting point for rendering when we **mount** the application.
6034

61-
When this data changes, the view will re-render. It should be noted that properties in `data` are only **reactive** if they existed when the instance was created. That means if you add a new property, like:
35+
An application needs to be mounted into a DOM element. For example, if we want to mount a Vue application into `<div id="app"></div>`, we should pass `#app`:
6236

6337
```js
64-
vm.b = 'hi'
38+
const RootComponent = { /* options */ }
39+
const app = Vue.createApp(RootComponent)
40+
const vm = app.mount('#app')
6541
```
6642

67-
Then changes to `b` will not trigger any view updates. If you know you'll need a property later, but it starts out empty or non-existent, you'll need to set some initial value. For example:
43+
Unlike most of the application methods, `mount` does not return the application. Instead it returns the root component instance.
6844

69-
```js
70-
data() {
71-
return {
72-
newTodoText: '',
73-
visitCount: 0,
74-
hideCompletedTodos: false,
75-
todos: [],
76-
error: null
77-
}
78-
}
79-
```
45+
Although not strictly associated with the [MVVM pattern](https://en.wikipedia.org/wiki/Model_View_ViewModel), Vue's design was partly inspired by it. As a convention, we often use the variable `vm` (short for ViewModel) to refer to a component instance.
8046

81-
The only exception to this being the use of `Object.freeze()`, which prevents existing properties from being changed, which also means the reactivity system can't _track_ changes.
47+
While all the examples on this page only need a single component, most real applications are organized into a tree of nested, reusable components. For example, a Todo application's component tree might look like this:
8248

83-
```js
84-
const obj = {
85-
foo: 'bar'
86-
}
49+
```
50+
Root Component
51+
└─ TodoList
52+
├─ TodoItem
53+
│ ├─ DeleteTodoButton
54+
│ └─ EditTodoButton
55+
└─ TodoListFooter
56+
├─ ClearTodosButton
57+
└─ TodoListStatistics
58+
```
8759

88-
Object.freeze(obj)
60+
Each component will have its own component instance, `vm`. For some components, such as `TodoItem`, there will likely be multiple instances rendered at any one time. All of the component instances in this application will share the same application instance.
8961

90-
const vm = Vue.createApp({
91-
data() {
92-
return obj
93-
}
94-
}).mount('#app')
95-
```
62+
We'll talk about [the component system](component-basics.html) in detail later. For now, just be aware that the root component isn't really any different from any other component. The configuration options are the same, as is the behavior of the corresponding component instance.
9663

97-
```html
98-
<div id="app">
99-
<p>{{ foo }}</p>
100-
<!-- this will no longer update `foo`! -->
101-
<button v-on:click="foo = 'baz'">Change it</button>
102-
</div>
103-
```
64+
## Component Instance Properties
10465

105-
In addition to data properties, instances expose a number of useful instance properties and methods. These are prefixed with `$` to differentiate them from user-defined properties. For example:
66+
Earlier in the guide we met `data` properties. Properties defined in `data` are exposed via the component instance:
10667

10768
```js
108-
const vm = Vue.createApp({
69+
const app = Vue.createApp({
10970
data() {
110-
return {
111-
a: 1
112-
}
71+
return { count: 4 }
11372
}
114-
}).mount('#example')
73+
})
11574

116-
vm.$data.a // => 1
75+
const vm = app.mount('#app')
76+
77+
console.log(vm.count) // => 4
11778
```
11879

119-
In the future, you can consult the [API reference](../api/instance-properties.html) for a full list of instance properties and methods.
80+
There are various other component options that add user-defined properties to the component instance, such as `methods`, `props`, `computed`, `inject` and `setup`. We'll discuss each of these in depth later in the guide. All of the properties of the component instance, no matter how they are defined, will be accessible in the component's template.
81+
82+
Vue also exposes some built-in properties via the component instance, such as `$attrs` and `$emit`. These properties all have a `$` prefix to avoid conflicting with user-defined property names.
12083

121-
## Instance Lifecycle Hooks
84+
## Lifecycle Hooks
12285

123-
Each instance goes through a series of initialization steps when it's created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes. Along the way, it also runs functions called **lifecycle hooks**, giving users the opportunity to add their own code at specific stages.
86+
Each component instance goes through a series of initialization steps when it's created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes. Along the way, it also runs functions called **lifecycle hooks**, giving users the opportunity to add their own code at specific stages.
12487

12588
For example, the [created](../api/options-lifecycle-hooks.html#created) hook can be used to run code after an instance is created:
12689

12790
```js
12891
Vue.createApp({
12992
data() {
130-
return {
131-
a: 1
132-
}
93+
return { count: 1 }
13394
},
13495
created() {
13596
// `this` points to the vm instance
136-
console.log('a is: ' + this.a) // => "a is: 1"
97+
console.log('count is: ' + this.count) // => "count is: 1"
13798
}
13899
})
139100
```

src/guide/template-syntax.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Template Syntax
22

3-
Vue.js uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying application instance's data. All Vue.js templates are valid HTML that can be parsed by spec-compliant browsers and HTML parsers.
3+
Vue.js uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying component instance's data. All Vue.js templates are valid HTML that can be parsed by spec-compliant browsers and HTML parsers.
44

55
Under the hood, Vue compiles the templates into Virtual DOM render functions. Combined with the reactivity system, Vue is able to intelligently figure out the minimal number of components to re-render and apply the minimal amount of DOM manipulations when the app state changes.
66

@@ -16,7 +16,7 @@ The most basic form of data binding is text interpolation using the "Mustache" s
1616
<span>Message: {{ msg }}</span>
1717
```
1818

19-
The mustache tag will be replaced with the value of the `msg` property on the corresponding data object. It will also be updated whenever the data object's `msg` property changes.
19+
The mustache tag will be replaced with the value of the `msg` property from the corresponding component instance. It will also be updated whenever the `msg` property changes.
2020

2121
You can also perform one-time interpolations that do not update on data change by using the [v-once directive](../api/directives.html#v-once), but keep in mind this will also affect any other bindings on the same node:
2222

@@ -123,7 +123,7 @@ in the "Dynamic Argument Expression Constraints" section below.
123123
<a v-bind:[attributeName]="url"> ... </a>
124124
```
125125

126-
Here `attributeName` will be dynamically evaluated as a JavaScript expression, and its evaluated value will be used as the final value for the argument. For example, if your application instance has a data property, `attributeName`, whose value is `"href"`, then this binding will be equivalent to `v-bind:href`.
126+
Here `attributeName` will be dynamically evaluated as a JavaScript expression, and its evaluated value will be used as the final value for the argument. For example, if your component instance has a data property, `attributeName`, whose value is `"href"`, then this binding will be equivalent to `v-bind:href`.
127127

128128
Similarly, you can use dynamic arguments to bind a handler to a dynamic event name:
129129

0 commit comments

Comments
 (0)