选项
1. data
-
类型:
Function
-
详细:
返回组件对应的各种数据。
实例创建后,可以通过
vm.$data
访问这些数据,组件实例也代理了 data 对象上所有的 property,因此访问vm.a
等价于访问vm.$data.a
。需要注意的是,不允许后续添加初始
data
中没有配置的属性,所以我们需要一开始在就在data
中配置好当前组件需要用的所有属性(数据)。 -
示例:
Vue.createApp({ data() { return { x: 10 } } })
2. methods
-
类型:
{ [key: string]: Function }
-
详细:
methods 将被混入到组件实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的
this
自动绑定为组件实例。注意,不应该使用箭头函数来定义 method 函数 (例如 plus:() => this.a++)。理由是箭头函数绑定了父级作用域的上下文,所以
this
将不会按照期望指向组件实例,this.a
将是 undefined。 -
示例:
const app = Vue.createApp({ data() { return { a: 1 } }, methods: { plus() { this.a++ } } }) const vm = app.mount('#app') vm.plus() console.log(vm.a) // => 2
3. 计算属性和侦听器
3.1 computed
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如,有一个嵌套数组对象:
Vue.createApp({
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
}
}
}
})
我们想根据 author
是否已经有一些书来显示不同的消息
<div id="computed-basics">
<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
</div>
此时,模板不再是简单的和声明性的。你必须先看一下它,然后才能意识到它执行的计算取决于 author.books
。如果要在模板中多次包含此计算,则问题会变得更糟。
所以,对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性。
<div id="computed-basics">
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</div>
Vue.createApp({
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
}
}
},
computed: {
// 计算属性的 getter
publishedBooksMessage() {
// `this` 指向 vm 实例
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
}).mount('#computed-basics')
当数据中 books
数组长度发生变化时,publishedBooksMessage
也会自动更变。
3.2 计算属性 vs 方法
你可能已经注意到我们可以通过在表达式中调用方法来达到同样的效果:
<p>{{ calculateBooksMessage() }}</p>
// 在组件中
methods: {
calculateBooksMessage() {
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
他们的区别在于计算属性是基于它们的反应依赖关系缓存的。计算属性只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 author.books
还没有发生改变,多次访问 publishedBookMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。
这也同样意味着下面的计算属性将不再更新,因为 Date.now () 不是响应式依赖:
computed: {
now() {
return Date.now()
}
}
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
3.3 计算属性的Setter
计算属性默认只有 getter,不过在需要时你也可以提供一个 setter:
// ...
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ...
现在再运行 vm.fullName = 'John Doe'
时,setter 会被调用,vm.firstName
和 vm.lastName
也会相应地被更新。
3.4 侦听器
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
使用 watch
选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
3.5 计算属性 vs 侦听器
Vue 提供了一种更通用的方式来观察和响应当前活动的实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch
——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch
回调。细想一下这个例子:
<div id="demo">{{ fullName }}</div>
const vm = Vue.createApp({
data() {
return {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
}
},
watch: {
firstName(val) {
this.fullName = val + ' ' + this.lastName
},
lastName(val) {
this.fullName = this.firstName + ' ' + val
}
}
}).mount('#demo')
上面代码是命令式且重复的。将它与计算属性的版本进行比较:
const vm = Vue.createApp({
data() {
return {
firstName: 'Foo',
lastName: 'Bar'
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
}).mount('#demo')
好很多了,不是吗?
4. delimiters
用于修改默认的双大括号插值写法,默认值:[', ']
。一般用于避免和其他同样使用双大括号的框架出现冲突。
Vue.createApp({
// 分隔符变成了 ES6 模板字符串风格
delimiters: ['${', '}']
})
5. 生命周期钩子
-
beforeCreate
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
-
created
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,
$el
property 目前尚不可用。 -
beforeMount
在挂载开始之前被调用:相关的
render
函数首次被调用。 -
mounted
实例被挂载后调用,这时
Vue.createApp({}).mount()
被新创建的vm.$el
替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时vm.$el
也在文档内。注意
mounted
不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在mounted
内部使用 vm.$nextTick (opens new window):mounted() { this.$nextTick(function () { // 仅在渲染整个视图之后运行的代码 }) }
-
beforeUpdate
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
-
updated
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
-
beforeUnmount
在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
-
unmounted
卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
6. 其他
以下选项和组件密切相关,在学习组件后,我们再来讨论这些选项的作用。
- props
- components
- mixins
- provide / inject
- name
- emits
- ……
评论(0)
暂无评论