Vue's computed and monitored properties

1. Vue computed properties

Let's take a look at an example first: (What needs to be implemented is after entering the fields in the input boxes of the first and last name, the full name will be spliced ​​below):

The first implementation method:

<body>
    <div id="root">
        <input type="text" v-model="fname"><br/><br/>
        <input type="text" v-model="lname"><br/><br/>
        <span>{
   
   {fullname()}}</span>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    fname: '申',
                    lname: '颖'
                }
            },
            methods: {
                fullname() {
                    return this.fname + '-' + this.lname;
                }

            },
        })
    </script>
</body>

Show results:

 The second implementation method:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="root">
        <input type="text" v-model="fname"><br/><br/>
        <input type="text" v-model="lname"><br/><br/>
        <span>{
   
   {fullname}}</span>
        <span>{
   
   {fullname}}</span>
        <span>{
   
   {fullname}}</span>
        <span>{
   
   {fullname}}</span>

    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    fname: '申',
                    lname: '颖'
                }
            },
            computed: {
                fullname: {
                    // get的作用:当有人读取fullname时,get就会被调用,且返回值作为fullname的值
                    // get什么时候被调用:
                    // 1.初次读取fullname时
                    // 2.所依赖的数据发生变化时
                    get() {
                        console.log('get被调用了');
                        return this.fname + '-' + this.lname;
                    },
                    // set什么时候被调用:当fullname被修改的时候
                    set(value) {
                        console.log('set', value);
                        const arr = value.split('-');
                        this.fname = arr[0];
                        this.lname = arr[1];
                    }
                }
            }
        })
    </script>
</body>

</html>

Look at the above code carefully

 I thought the fullname function would be called four times, but it was actually called only once. If it was the first method, it would be called four times. Because computed properties have their own caching mechanism.

To summarize computed properties:

1. Definition: The attribute to be used does not exist and must be calculated from the existing attributes.

2. Principle: The bottom layer uses the getter and setter provided by the Object.defineProperty method

3. When is the get function executed?

(1) It will be executed once when reading for the first time

(2) When the dependent data changes, it will be called again

4. Advantages: Compared with the implementation of methods, there is a cache mechanism (multiplexing) inside, which is more efficient and easier to debug.

5. Remarks:

(1) Computed attributes will eventually appear on the vm, just read and use them directly

(2) If the calculated attribute is to be modified, the set function must be written to respond to the modification, and the set will cause the data dependent on the calculation to occur

If you only need to read computed properties, you can use the following shorthand:

<body>
    <div id="root">
        <input type="text" v-model="fname"><br/><br/>
        <input type="text" v-model="lname"><br/><br/>
        <span>{
   
   {fullname}}</span>
        <span>{
   
   {fullname}}</span>
        <span>{
   
   {fullname}}</span>
        <span>{
   
   {fullname}}</span>

    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    fname: '申',
                    lname: '颖'
                }
            },
            computed: {
                fullname() {
                    return this.fname + '-' + this.lname;
                }
            }
        })
    </script>
</body>

Two, Vue monitoring properties

There are two ways to write the monitoring attribute

(1) Writing 1

<body>
    <div id="root">
        <h2>今天天气很{
   
   {info}}</h2>
        <button @click="change">切换按钮</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    ishot: true
                }
            },
            computed: {
                info() {
                    return this.ishot ? "热" : "不热"
                }
            },
            methods: {
                change() {
                    return this.ishot = !this.ishot;
                }
            },
            watch: {
                ishot: {
                    // immediate代表初始化时让handler调用一下
                    immediate: true,
                    // handler什么时候调用?当ishot发生改变时
                    handler(newvalue, oldvalue) {
                        console.log('ishot is change', newvalue, oldvalue);
                    }   
                }
            }
        })
    </script>
</body>

(2) Writing method two

<body>
    <div id="root">
        <h2>今天天气很{
   
   {info}}</h2>
        <button @click="change">切换按钮</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    ishot: true
                }
            },
            computed: {
                info() {
                    return this.ishot ? "热" : "不热"
                }
            },
            methods: {
                change() {
                    return this.ishot = !this.ishot;
                }
            }
        })
        vm.$watch('ishot', {
            immediate: true,
            handler(newvalue, oldvalue) {
                console.log('ishot is change', newvalue, oldvalue);
            }
        })
    </script>
</body>

Notes on monitoring attribute watch:

(1) When the monitored attribute changes, the callback function (handler) is automatically called to perform related operations

(2) The monitored attribute must exist in order to be monitored

(3) Two ways of writing monitoring:

1. When new Vue is passed in watch configuration

2. Monitor through vm.$watch

(3) In-depth monitoring

<body>
    <div id="root">
        <hr>
        <h3>a的值为{
   
   {number.a}}</h3>
        <button @click="adda">执行a++</button>
        <hr>
        <h3>b的值为{
   
   {number.b}}</h3>
        <button @click="addb">执行b++</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    ishot: true,
                    number: {
                        a: 1,
                        b: 2
                    }
                }
            },
            methods: {
                adda() {
                    return this.number.a++;
                },
                addb() {
                    return this.number.b++;
                }
            },
            watch: {
                immediate: true,
                // 监视多级结构中所有属性的变化
                number: {
                    // deep加上了就代表a或者b变化了都会执行handler函数,如果不加就是整个number变了才会执行handler函数
                    deep: true,
                    handler() {
                        console.log('number被改变了');
                    }
                }
            }
        })
    </script>
</body>

Points to note for in-depth monitoring:

(1) The watch in Vue does not monitor the change of the internal value of the object by default (one layer)

(2) Configure deep: true to monitor the internal value of the object to change (multi-layer)

Remark:

(1) Vue itself can monitor the change of the internal value of the object, but the watch provided by Vue cannot by default

(2) When using watch, according to the specific structure of the data, it is decided whether to use in-depth monitoring

(4) Abbreviated form of monitoring

The abbreviated form can only be used when the configuration item in the watch is only handler

Short form one:

<body>
    <div id="root">
        <h2>今天天气很{
   
   {info}}</h2>
        <button @click="change">切换按钮</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    ishot: true
                }
            },
            computed: {
                info() {
                    return this.ishot ? "热" : "不热"
                }
            },
            methods: {
                change() {
                    return this.ishot = !this.ishot;
                }
            },
            watch: {
                ishot(newvalue, oldvalue) {
                    console.log('ishot is change', newvalue, oldvalue);
                }
            }
        })
    </script>
</body>

Short form two:

<body>
    <div id="root">
        <h2>今天天气很{
   
   {info}}</h2>
        <button @click="change">切换按钮</button>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    ishot: true
                }
            },
            computed: {
                info() {
                    return this.ishot ? "热" : "不热"
                }
            },
            methods: {
                change() {
                    return this.ishot = !this.ishot;
                }
            }
        })
        vm.$watch('ishot', function(newvalue, oldvalue) {
            console.log('ishot is change', newvalue, oldvalue);
        })
    </script>
</body>

3. Comparison of calculated attributes and monitored attributes

Use the monitoring attribute to realize the previous example of splicing the first name and last name into a full name, and it will be displayed after 1 second after an additional input

<body>
    <div id="root">
        <input type="text" v-model="fname"><br/><br/>
        <input type="text" v-model="lname"><br/><br/>
        <span>{
   
   {fullname}}</span>
    </div>
    <script>
        Vue.config.productionTip = false;
        const vm = new Vue({
            el: '#root',
            data: function() {
                return {
                    fname: '申',
                    lname: '颖',
                    fullname: '申-颖'
                }
            },
            watch: {
                fname(val) {
                    // 这里定时器的函数只能写成箭头函数
                    // 是因为箭头函数没有this就会往外找,就是fname的this,fname的this就是vue所管理的函数,所以是vm
                    // 如果写成setTimeout(function(){})的话this指向的就是windows了
                    setTimeout(() => {
                        console.log(this);
                        this.fullname = val + '-' + this.lname;
                    }, 1000)
                },
                lname(val) {
                    setTimeout(() => {
                        this.fullname = this.fname + '-' + val;
                    }, 1000)
                }
            }
        })
    </script>
</body>

If you write with a computed property:

 There is a problem with this part. The value returned by your return is given to setTimeout instead of fullName, so it cannot be rendered without the value of the computed property at all.

The difference between computed properties and watched properties:

(1) The functions that can be completed by calculating attributes can be completed by monitoring attributes

(2) Functions that can be completed by monitoring attributes may not necessarily be completed by computing attributes, for example, monitoring attributes can perform asynchronous operations.

Two important little principles:

(1) All functions managed by Vue are best written as ordinary functions, so that the execution of this is the vm or component instance object

(2) For all functions not managed by Vue (timer callback function, ajax callback function, Promise callback function, etc.), it is best to write arrow functions, so that the point of this is the vm or component instance object

Guess you like

Origin blog.csdn.net/qq_43781887/article/details/127485687