The principle of Vue2 data two-way binding

For the understanding of vue2 data two-way binding, you will have a better understanding after typing it by hand~

1. Part of the page data

        Before implementing data two-way binding, we first prepare the data we need to use, and then implement the code part

(1) Page structure

Here it is necessary to complete the correlation between         the data bound by v-model and the value in the interpolation expression of the page structure, so as to achieve the effect of two-way data binding of vue

<body id="app">
    <span>up主:{
   
   { name }}</span>
    <input type="text" v-model="name">
    <span>更多:{
   
   { more.like }}</span>
    <input type="text" v-model="more.like">
</body>

(2) script part

        The vue file imported through the script tag part is not the real vue , that is, the code part we will write immediately

         In el, we store the id in the <body/> tag of the html part for our convenience in the future

<script src="./vue.js"></script>
<script>
    const vm = new Vue(
        {
            el: '#app',
            data: {
                name: 'kerwin',
                more: {
                    like: '点赞'
                }
            }
        }
    )
    console.log(vm);
</script>

Two, vue.js code

(1) Create a Vue instance

        Because we even consider the amount of code is relatively large, and we need to use constructors, so we choose the class class to create constructors

        The object passed when obj_instance is an instance, first. We first save his data attribute to $data in the instance , but it is also used in vue

class Vue {
    constructor(obj_instance) {
        this.$data = obj_instance.data
    }
}

(2) Realize data hijacking

        Key point: We need to use Object.defineProperty to achieve data hijacking . This is the case in vue2, but vue3 is slightly different. It is not difficult to understand vue3 after understanding vue2

     1. Create a function for data hijacking

        Because what we need two-way binding is the data in data, so we need to pass data

class Vue {
    constructor(obj_instance) {
       // ....
       // 在构造函数中将data 传入
        Observer(this.$data)
    }
}

// 实现数据劫持
function Observer(data_instance) {


}

        2. Traverse the data object and implement data hijacking

           Understanding: Object.defineProperty

            Object.defineProperty( object of operation, property of operation, { } ) 

             { } Pass in the object, and implement data monitoring in the object

            This method can modify the existing properties in the object

// 数据劫持
function Observer(data_instance) {
    // 遍历对象中的每一个属性
    Object.keys(data_instance).forEach(key => {
        Object.defineProperty(data_instance, key, {
            // 设置属性描述符可以改变
            configurable: true,
            // 设置是否可枚举
            enumerable: true,
            get() {

            },
            set(newValue) {

            },
        })
    })
}

        3. Set up setters and getters

        We can check the data in the console before setting

        ① getter

        Let's output vm before observer. When we access the attribute value in vm, we find that the data is undefined , because we get and do not return when accessing , resulting in data loss

        So when we traverse the key, we first save the data to the value variable. When we access it, get will be triggered and the value will be returned , so that the data will be fine.

        ② setter

        When we set the data in vm, the set function will be triggered, and its formal parameter (newValue) is the data we set, so we can directly set the value as newValue , and the data can be modified normally at this time

// 数据劫持
function Observer(data_instance) {
    // 如果没有值或不为对象那么直接返回出去
    Object.keys(data_instance).forEach(key => {

++      let value = data_instance[key]

        Object.defineProperty(data_instance, key, {
            configurable: true,
            enumerable: true,

            get() {
++              console.log(`访问了${key}属性 -->  属性值为:${value}`);
++              return value // 将原本数据return出来
            },
            set(newValue) {
++              value = newValue
++              console.log(`修改了${key}属性值${value} --> 为${newValue}`);
            },
        })
    })
}

        4. Process the object in the data object attribute

        Because there are also objects in the data attribute value we set, we use object.key to traverse only the first layer. If we want to hijack all the data in data, then we need to use recursion

        When we traverse the key, we first call recursively to see if there is a value or data type as an object. If so, continue recursing to solve this problem.

function Observer(data_instance) {

    // 如果没有值或不为对象那么直接返回出去
++  if (!data_instance || typeof data_instance !== 'object') return

    Object.keys(data_instance).forEach(key => {
        let value = data_instance[key]
        // 递归,内部属性
++      Observer(value)

        Object.defineProperty(data_instance, key, {
           // ....
        })
    })
}

        5. Handle assigning a new object to a property

        When we reassign a property to an object, it will not recurse, because observe has already run, so we need to call observe again in the setter

Object.defineProperty(data_instance, key, {
    // ...

    set(newValue) {
        // 递归
++      Observer(newValue)
        value = newValue
        return console.log(`修改了${key}属性值${value} --> 为${newValue}`);
    },
})

There are too many, so I won’t explain it, I will add it later

For details, see gitee and clone it. The address is as follows

Vue2 implements two-way binding of data: Vue2's two-way binding of data, covering v-model+input

Guess you like

Origin blog.csdn.net/Kerwin__li/article/details/128741065