[A glimpse of the series] Wue realizes the principle of two-way data binding

1. Understanding Object.defineProperty()

grammar:

Object.defineProperty(obj, prop, descriptor)

Parameter Description:

obj: Required. Target object 
prop: Required. The name of the property to be defined or modified
descriptor: Required. Properties owned by the target property

return value:

The object passed into the function. i.e. the first parameter obj

Add feature description to the properties of an object. Currently, two forms are provided: data description and accessor description.

A. Data description

When modifying or defining a property of an object, add some properties to the property:

var obj = {
    test:"hello"
}
//对象已有的属性添加特性描述
Object.defineProperty(obj,"test",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false
});
//对象新添加的属性的特性描述
Object.defineProperty(obj,"newKey",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false
});

The attributes in the data description are optional, let's take a look at the effect of setting each attribute.

Summary of the properties of the settings:

value: set the value of the property
writable: whether the value can be overridden. true | false
enumerable: Whether the target property can be enumerated. true | false
configurable: whether the target property can be deleted or whether the property can be modified again true | false

B. Accessor Description

When using accessors to describe the properties of a property, it is allowed to set the following property properties:

var obj = {};
Object.defineProperty(obj,"newKey",{
    get:function (){} | undefined,
    set:function (value){} | undefined
    configurable: true | false
    enumerable: true | false
});

Note: When using getter or setter methods, the use of writable and value property getters/setters is not allowed

When setting or getting the value of a property of an object, you can provide getter/setter methods.

  • A getter is a way to get the value of a property

  • A setter is a way to set the value of a property.

Use the get/set attribute in the attribute to define the corresponding method.

var obj = {};
var initValue = 'hello';
Object.defineProperty(obj,"newKey",{
    get:function (){
        //当获取值的时候触发的函数
        return initValue;    
    },
    set:function (value){
        //当设置值的时候触发的函数,设置的新值通过参数value拿到
        initValue = value;
    }
});
//获取值
console.log( obj.newKey );  //hello

//设置值
obj.newKey = 'change value';

console.log( obj.newKey ); //change value

Note: get or set does not have to appear in pairs, you can write either one. If no method is set, the default value of get and set is undefined; configurable and enumerable are the same as above.

C. Compatibility

Under ie8, it can only be used on DOM objects. If you try to use Object.defineProperty() on native objects, an error will be reported.

2. Basic Examples

Simple demo, unfortunately, {{ message }} template parsing has not been implemented yet

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>Wue 双向绑定实现原理</title>
</head>
<body>
<div id="app">
  <input type="text" w-model="message"/>
  <p>我会改变:<span id="message">message</span></p>
</div>
<script>
  // A.定义一个空对象, 获取被w-model设置的input
  let obj = {};
  let prop = document.querySelector('[w-model]').getAttribute('w-model');

  // 模板引擎函数
  let whtml = function (source, data) {
    let match;
    let reg = /{{(.+?)}}/g;
    while ((match = reg.exec(source)) !== null) {
      if (match[1]) {
        match[1] = match[1].replace(/\s/g, '');
        source = source.replace(match[0], data)
      } else {
        source = source.replace(match[0], '')
      }
    }
    return source
  };

  // B.精髓所在
  Object.defineProperty(obj, prop, {
    get: function () {
      return obj;
    },
    set: function (newValue) {
      document.querySelector('[w-model=message]').value = newValue;
      // let app = document.getElementById('app');
      // app.innerHTML = whtml(app.innerHTML, newValue);
      document.getElementById('message').innerHTML = newValue;
    }
  });

  // C.添加input事件监听
  document.addEventListener('input', function (e) {
    obj[prop] = e.target.value;
  });
</script>
</body>
</html>

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324977473&siteId=291194637