Skip to content

Migrate instance methods API #78

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ const sidebar = {
'/api/options-misc'
]
},
'/api/instance-properties.md'
'/api/instance-properties.md',
'/api/instance-methods.md'
]
}

Expand Down
277 changes: 277 additions & 0 deletions src/api/instance-methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
# Instance Methods

## $watch

- **Arguments:**

- `{string | Function} source`
- `{Function | Object} callback`
- `{Object} [options]`
- `{boolean} deep`
- `{boolean} immediate`

- **Returns:** `{Function} unwatch`

- **Usage:**

Watch an expression or a computed function on the Vue instance for changes. The callback gets called with the new value and the old value. The expression only accepts dot-delimited paths. For more complex expressions, use a function instead.

- **Example:**

```js
const app = Vue.createApp({
data() {
return {
a: 1,
b: 2
}
},
created() {
// keypath
this.$watch('a', (newVal, oldVal) => {
// do something
})

// function
this.$watch(
// every time the expression `this.a + this.b` yields a different result,
// the handler will be called. It's as if we were watching a computed
// property without defining the computed property itself
() => this.a + this.b,
(newVal, oldVal) => {
// do something
}
)
}
})
```

When watched value is an Object or Array, any changes to its properties or elements won't trigger the watcher because they reference the same Object/Array:

```js
const app = Vue.createApp({
data() {
return {
article: {
text: 'Vue is awesome!'
},
comments: ['Indeed!', 'I agree']
}
},
created() {
this.$watch('article', () => {
console.log('Article changed!')
})

this.$watch('comments', () => {
console.log('Comments changed!')
})
},
methods: {
// These methods won't trigger a watcher because we changed only a property of Object/Array,
// not the Object/Array itself
changeArticleText() {
this.article.text = 'Vue 3 is awesome'
},
addComment() {
this.comments.push('New comment')
},

// These methods will trigger a watcher because we replaced Object/Array completely
changeWholeArticle() {
this.article = { text: 'Vue 3 is awesome' }
},
clearComments() {
this.comments = []
}
}
})
```

`$watch` returns an unwatch function that stops firing the callback:

```js
const app = Vue.createApp({
data() {
return {
a: 1
}
}
})

const vm = app.mount('#app')

const unwatch = vm.$watch('a', cb)
// later, teardown the watcher
unwatch()
```

- **Option: deep**

To also detect nested value changes inside Objects, you need to pass in `deep: true` in the options argument. Note that you don't need to do so to listen for Array mutations.

```js
vm.$watch('someObject', callback, {
deep: true
})
vm.someObject.nestedValue = 123
// callback is fired
```

- **Option: immediate**

Passing in `immediate: true` in the option will trigger the callback immediately with the current value of the expression:

```js
vm.$watch('a', callback, {
immediate: true
})
// `callback` is fired immediately with current value of `a`
```

Note that with `immediate` option you won't be able to unwatch the given property on the first callback call.

```js
// This will cause an error
const unwatch = vm.$watch(
'value',
function() {
doSomething()
unwatch()
},
{ immediate: true }
)
```

If you still want to call an unwatch function inside the callback, you should check its availability first:

```js
const unwatch = vm.$watch(
'value',
function() {
doSomething()
if (unwatch) {
unwatch()
}
},
{ immediate: true }
)
```

- **See also:** [Watchers](../guide/computed.html#watchers)

## $emit

- **Arguments:**

- `{string} eventName`
- `[...args]`

Trigger an event on the current instance. Any additional arguments will be passed into the listener's callback function.

- **Examples:**

Using `$emit` with only an event name:

```html
<div id="emit-example-simple">
<welcome-button v-on:welcome="sayHi"></welcome-button>
</div>
```

```js
const app = Vue.createApp({
methods: {
sayHi() {
console.log('Hi!')
}
}
})

app.component('welcome-button', {
template: `
<button v-on:click="$emit('welcome')">
Click me to be welcomed
</button>
`
})

app.mount('#emit-example-simple')
```

Using `$emit` with additional arguments:

```html
<div id="emit-example-argument">
<advice-component v-on:give-advice="showAdvice"></advice-component>
</div>
```

```js
const app = Vue.createApp({
methods: {
showAdvice(advice) {
alert(advice)
}
}
})

app.component('advice-component', {
data() {
return {
adviceText: 'Some advice'
}
},
template: `
<div>
<input type="text" v-model="adviceText">
<button v-on:click="$emit('give-advice', adviceText)">
Click me for sending advice
</button>
</div>
`
})
```

- **See also:**
- [`emits` option](./options-data.html#emits)
- [Emitting a Value With an Event](../guide/component-basics.html#emitting-a-value-with-an-event)

## $forceUpdate

- **Usage:**

Force the Vue instance to re-render. Note it does not affect all child components, only the instance itself and child components with inserted slot content.

## $nextTick

- **Arguments:**

- `{Function} [callback]`

- **Usage:**

Defer the callback to be executed after the next DOM update cycle. Use it immediately after you've changed some data to wait for the DOM update. This is the same as the global `Vue.nextTick`, except that the callback's `this` context is automatically bound to the instance calling this method.

- **Example:**

```js
Vue.createApp({
// ...
methods: {
// ...
example() {
// modify data
this.message = 'changed'
// DOM is not updated yet
this.$nextTick(function() {
// DOM is now updated
// `this` is bound to the current instance
this.doSomethingElse()
})
}
}
})
```

- **See also:** [Vue.nextTick](TODO)
4 changes: 2 additions & 2 deletions src/api/options-lifecycle-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ All lifecycle hooks automatically have their `this` context bound to the instanc

Called after the instance has been mounted, where element, passed to `Vue.createApp({}).mount()` is replaced by the newly created `vm.$el`. If the root instance is mounted to an in-document element, `vm.$el` will also be in-document when `mounted` is called.

Note that `mounted` does **not** guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use [vm.\$nextTick](TODO) inside of `mounted`:
Note that `mounted` does **not** guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use [vm.$nextTick](../api/instance-methods.html#nexttick) inside of `mounted`:

```js
mounted() {
Expand Down Expand Up @@ -81,7 +81,7 @@ All lifecycle hooks automatically have their `this` context bound to the instanc

The component's DOM will have been updated when this hook is called, so you can perform DOM-dependent operations here. However, in most cases you should avoid changing state inside the hook. To react to state changes, it's usually better to use a [computed property](./options-data.html#computed) or [watcher](./options-data.html#watch) instead.

Note that `updated` does **not** guarantee that all child components have also been re-rendered. If you want to wait until the entire view has been re-rendered, you can use [vm.\$nextTick](TODO) inside of `updated`:
Note that `updated` does **not** guarantee that all child components have also been re-rendered. If you want to wait until the entire view has been re-rendered, you can use [vm.$nextTick](../api/instance-methods.html#nexttick) inside of `updated`:

```js
updated() {
Expand Down
2 changes: 1 addition & 1 deletion src/guide/component-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ When we click on the button, we need to communicate to the parent that it should
<blog-post ... v-on:enlarge-text="postFontSize += 0.1"></blog-post>
```

Then the child component can emit an event on itself by calling the built-in [**`$emit`** method](TODO:../api/#vm-emit), passing the name of the event:
Then the child component can emit an event on itself by calling the built-in [**`$emit`** method](../api/instance-methods.html#emit), passing the name of the event:

```html
<button v-on:click="$emit('enlarge-text')">
Expand Down
2 changes: 1 addition & 1 deletion src/guide/computed.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ Result:

In this case, using the `watch` option allows us to perform an asynchronous operation (accessing an API) and sets a condition for performing this operation. None of that would be possible with a computed property.

In addition to the `watch` option, you can also use the imperative [vm.\$watch API](TODO:../api/#vm-watch).
In addition to the `watch` option, you can also use the imperative [vm.$watch API](../api/instance-methods.html#watch).

### Computed vs Watched Property

Expand Down
2 changes: 1 addition & 1 deletion src/guide/instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const vm = Vue.createApp().mount(
vm.$data.a // => 1
```

In the future, you can consult the [API reference](TODO:../api/#Instance-Properties) for a full list of instance properties and methods.
In the future, you can consult the [API reference](../api/instance-properties.html) for a full list of instance properties and methods.

## Instance Lifecycle Hooks

Expand Down