温故知新 Vue 3: Lesson 2
Vue 的 Data Properties and Methods
Data Properties
const app = Vue.createApp({
data() {
return { count: 4 };
},
});
const vm = app.mount("#app");
The data option for a component is a function.
组件的 data option 是一个函数
wrap in its reactivity system and store on the component instance as $data.
创建一个组件实例的时候, 会调用这个 data 函数, 返回的对象会被包含到 Vue 的反应系统里. 并且以 $data 为 property key 存在实例对象上
any top-level properties of that object are also exposed directly via the component instance
data option 里面最顶层的属性也通过 proxy 直接暴露在组件实例的 property 上
console.log(vm.$data.count); // => 4
console.log(vm.count); // => 4
// Assigning a value to vm.count will also update $data.count
vm.count = 5;
console.log(vm.$data.count); // => 5
// ... and vice-versa
vm.$data.count = 6;
console.log(vm.count); // => 6
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.
这些实例的属性只会在实例创建的时候添加, 你必须保证所有需要的的 property 都已经存在.
Where necessary, use null, undefined or some other placeholder value
必要的话, 可以用 null, undefined, 或 空字符串 "" 初始化他们
It is possible to add a new property directly to the component instance. because this property isn't backed by the reactive $data object, it won't automatically be tracked by Vue's reactivity system.
后面直接添加到组件实例上的 property, 不会被 Vue 的反应系统所 track.
Vue uses a $ prefix when exposing its own built-in APIs via the component instance. It also reserves the prefix _ for internal properties.
Vue 使用 $ prefix 表示内部 api, 使用 _ prefix 表示内部 property. 用户如果有需要的话, 可以使用 $_ prefix.
Methods
const app = Vue.createApp({
data() {
return { count: 4 };
},
methods: {
increment() {
// `this` will refer to the component instance
this.count++;
},
},
});
This should be an object containing the desired methods
对象里面包含所有 Template 里面需要访问的方法
Vue automatically binds the this value for methods so that it always refers to the component instance.
Vue 会自动对 methods object 里面的方法绑定 this. this 指向组件的实例.
avoid using arrow functions when defining methods
定义 method 的时候避免使用 arrow function 箭头函数. 因为 arrow function 没有自己的 this. 他会使用 parent scope 下的 this. 也就是上一级 {} 里的 this 含义.
但是有一种情况例外, 就是你的 method 里面还包含其他 function. 那么你里面的 function 最好使用箭头函数. 否则可以在 method block 的头部定义 that=this. 然后使用 that.
const app = Vue.createApp({
data() {
return { count: 4 };
},
methods: {
foo() {
// `this` will refer to the component instance
const that = this;
function innerFn() {
that.bar();
}
// 或者使用 arrow function
// const innerFn = () => {
// this.bar()
// }
innerFn();
},
bar() {},
},
});
Inside a template they are most commonly used as event listeners
method 通常被用来当做事件监听的 callback
<button @click="increment">Up vote</button>
method vs computed
<span :title="toTitleDate(date)"> {{ formatDate(date) }} </span>
<span :title="computedTitleDate"> {{ computedDate }} </span>
it's usually better to use a computed property instead. However, using a method can be useful in scenarios where computed properties aren't a viable option.
对于数据的加工处理, computed property 通常会比 method 合适. computed 的值会被 cache. 而 method 每次都需要重新计算. 但是如果 computed 不可用的情况, 使用 method. 在 template 里面任何可以使用 js 表达式的地方, 都可以使用 method.
If the methods toTitleDate or formatDate access any reactive data then it will be tracked as a rendering dependency.
如果 method 使用了 reactive data. 这个 method 会被当做 rendering dependenc 渲染依赖进行 track. 当 data 变化时, 会 trigger 这些 effect.
Methods called from a template should not have any side effects, such as changing data or triggering asynchronous processes.
直接在 template 里面调用的 method 不应该产生 side effects. 比如改变 data 或者 发起异步操作.
Debouncing and Throttling
import _ from "lodash";
Vue.createApp({
methods: {
// Debouncing with Lodash
click: _.debounce(function () {
// ... respond to click ...
}, 500),
},
}).mount("#app");
使用 lodash 里的 dobounce.
However, this approach is potentially problematic for components that are reused because they'll all share the same debounced function. add the debounced function in the created lifecycle hook
因为组件实例之间共享 method. 如果组件要重复利用, 又不是每个组件实例都需要 debounced function. 在 lifecycle 中去处理 debounce.
app.component("save-button", {
created() {
// Debouncing with Lodash
this.debouncedClick = _.debounce(this.click, 500);
},
unmounted() {
// Cancel the timer when the component is removed
this.debouncedClick.cancel();
},
methods: {
click() {
// ... respond to click ...
},
},
template: `
<button @click="debouncedClick">
Save
</button>
`,
});
本文使用 mdnice 排版