We know that some data in data can be displayed directly through interpolation syntax in the template, but in some cases, we may need to perform some transformations on the data before displaying it, or we need to Combining multiple data for display
Using expressions in templates can be very convenient, but they are originally designed for simple operations. Putting too much logic in the template will make the template It is too heavy and difficult to maintain, and if it is used in multiple places, there will be a lot of duplicate code
So we hope to separate the business logic and UI interface. One way is to extract the logic into a method, but this approach has the following disadvantages
All the data usage process will become a method call
Multiple acquisitions Data needs to call the method multiple times to execute the corresponding logic without caching
In fact, For any complex logic that contains responsive data, you should use calculated properties
<div id="app"> <!-- 计算属性的使用和普通状态的使用方式是一致的 --> <h3>{{ fullname }}</h3> </div> <script> Vue.createApp({ data() { return { firstname: 'Klaus', lastname: 'Wang' } }, computed: { fullname() { return this.firstname + ' ' + this.lastname } } }).mount('#app')
Computed properties will be cached based on their dependencies. When the data does not change, calculated properties do not need to be recalculated
But if When the dependent data changes, the calculated properties will still be recalculated when used
And the interface will be re-rendered using the latest calculated property values
Computed properties In most cases, only one getter method is needed, so we will write the calculated properties directly as a function
<div id="app"> <!-- 计算属性的使用和普通状态的使用方式是一致的 --> <h3>{{ fullname }}</h3> <button @click="change">change</button> </div> <script> Vue.createApp({ data() { return { firstname: 'Klaus', lastname: 'Wang' } }, methods: { change() { this.fullname = 'Alex Li' } }, computed: { // 计算属性的完整写法 fullname: { get() { return this.firstname + ' ' + this.lastname }, set(v) { this.firstname = v.split(' ')[0] this.lastname = v.split(' ')[1] } } } }).mount('#app') </script>
is defined in the object returned by data The data is bound to the template through interpolation syntax, etc. When the data changes, the template will automatically update to display the latest data
But in some cases, we hope that in the code logic To monitor changes in certain data, you need to use the listener watch at this time
Vue.createApp({ data() { return { info: { name: 'Klaus' } } }, watch: { // 可以使用watch监听响应式数据的改变 // 对应有两个参数 // 参数一 --- 新值 // 参数二 --- 旧值 info(newV, oldV) { // 如果监听的值是对象,获取到的新值和旧值是对应对象的代理对象 console.log(newV, oldV) // 代理对象 转 原生对象 // 1. 使用浅拷贝获取一个新的对象,获取的新的对象为原生对象 console.log({...newV}) // 2. 使用Vue.toRaw方法获取原生对象 console.log(Vue.toRaw(newV)) } }, methods: { change() { this.info = { name: 'Steven' } } } }).mount('#app')
Properties | Description |
---|---|
deep | Whether to turn on deep monitoring The value is boolean When it is not turned on, if the object is monitored, only the reference of the object occurs The watch callback will only be triggered when it changes After starting, if the object is monitored, then as long as any attribute in the object changes, the watch callback will be triggered |
immediate | Whether to start monitoring immediately By default, the watch monitoring will not be triggered for the first rendering. Only when the value changes, the watch monitoring will be triggered. After setting immediate to true, the watch monitoring will be triggered for the first time. Rendering will also trigger watch monitoring. At this time, the value of oldValue is undefined |
Vue.createApp({ data() { return { info: { name: 'Klaus' } } }, watch: { info: { // 开启了深度监听后,当info的属性发生改变的时候,就会触发对应的watch回调 // 注意: 和直接修改info引用不同的是,如果直接修改的是对象的属性 // 那么此时newV和oldV是同一个对象的引用, 此时也就获取不到对应的旧值 handler(newV, oldV) { console.log(newV, oldV) console.log(newV === oldV) // => true }, deep: true, immediate: true } }, methods: { change() { this.info.name = 'Steven' } } }).mount('#app')
Directly monitor the object properties
watch: { 'info.name'(newV, oldV){ console.log(newV, oldV) } }
String writing method
Vue.createApp({ data() { return { info: { name: 'Klaus' } } }, watch: { // watch的值如果是一个字符串的时候 // 会自动以该字符串作为函数名去methods中查找对应的方法 'info.name': 'watchHandler' }, methods: { change() { this.info.name = 'Steven' }, watchHandler(newV, oldV){ console.log(newV, oldV) } } }).mount('#app')
Array writing method
Vue.createApp({ data() { return { info: { name: 'Klaus' } } }, watch: { 'info.name': [ 'watchHandler', function handle() { console.log('handler2') }, { handler() { console.log('handler3') } } ] }, methods: { change() { this.info.name = 'Steven' }, watchHandler(){ console.log('handler1') } } }).mount('#app')
$watch
Vue.createApp({ data() { return { info: { name: 'Klaus' } } }, created() { /* $watch 参数列表 参数一 --- 侦听源 参数二 --- 侦听回调 参数三 --- 配置对象 */ this.$watch('info.name', (newV, oldV) => console.log(newV, oldV), { immediate: true }) }, methods: { change() { this.info.name = 'Steven' } } }).mount('#app')
The above is the detailed content of How to use computed properties and listeners in Vue3. For more information, please follow other related articles on the PHP Chinese website!