이번에는 Vue의 DefineProperty 속성 사용에 대해 알려드리겠습니다. Vue의 DefineProperty 속성 사용 시 주의사항은 무엇인가요?
1. 원리
Vue의 양방향 데이터 바인딩 원리는 주로 ES5 개체 개체의 DefineProperty 속성을 통해 구현된다는 것을 알고 있습니다. 실제 코드 개발에 ES6를 사용하지 마십시오. 프로세스 중에 함수가 상위 this를 사용하는 경우 처리를 위해 표시 캐시 중간 변수 및 클로저를 사용하십시오. 그 이유는 화살표 함수가 this를 독립적으로 실행하지 않기 때문입니다. 이 객체는 화살표 함수 내부에 나타납니다. 따라서 화살표 함수는 함수의 사용 시나리오를 완전히 대체할 수 없다는 것을 알 수 있습니다.
Syntax:
Object.defineProperty (obj, prop, descriptor)Parameters:
obj: 필요한 대상 객체
prop: 정의하거나 수정해야 하는 필수 속성 이름
descriptor: 소유한 필수 속성 대상 속성
반환 값:
첫 번째 매개변수인 obj를 반환합니다.
이 메서드를 사용하면 할당에 의해 추가된 일반 속성이 생성되고 표시됩니다. 속성 열거(fon... in; object.key); 이 추가된 값은 읽기 전용이지만 쓰기가 가능한지 여부와 같은 일부 특성을 설정하거나 삭제할 수 있습니다. 데이터 설명(설정; 가져오기; 값; 쓰기 가능; 열거 가능; 구성 가능) 및 접근자 설명(설정; 가져오기)
데이터 설명객체의 속성을 수정하거나 정의할 때 이 속성에 몇 가지 특성을 추가합니다.
var obj = { name:'xiangha' } // 对象已有的属性添加特性描述 Object.defineProperty(obj,'name',{ configurable:true | false, // 如果是false则不可以删除 enumerable:true | false, // 如果为false则在枚举时候会忽略 value:'任意类型的值,默认undefined' writable:true | false // 如果为false则不可采用数据运算符进行赋值 }); 但是存在一个交叉;如果wrirable为true;而configurable为false的时候;所以需要枚举处理enumerable为false --- 我是一个writable栗子 --- var obj = {}; Object.defineProperty(obj,'val',{ value:'xiangha', writable:false, // false enumerable:true, configurable:true }); obj.val = '书记'; // 这个时候是更改不了a的 --- 我是一个configurable栗子 --- var obj = {}; Object.defineProperty(obj,'val',{ value:'xiangha', writable:true, // true enumerable:true, configurable:false // false }); obj.val = '书记'; // 这个时候是val发生了改变 delete obj.val 会返回false;并且val没有删除 --- 我是一个enumerable栗子 --- var obj = {}; Object.defineProperty(obj,'val',{ value:'xiangha', writable:true, enumerable:false, // false configurable:true }); for(var i in obj){ console.log(obj[i]) // 没有具体值 } 综上:对于我们有影响主要是configurable控制是否可以删除;writable控制是否可以修改赋值;enumerable是否可以枚举
따라서 Object.defineProperty()를 사용하면 객체에 속성이 추가됩니다. 속성의 특성이 설정되지 않은 경우 기본값은 false입니다.var obj = {};
Object.defineProperty(obj,'name',{}); // 定义了心属性name后;这个属性的特性的值都为false;这就导致name这个是不能重写不能枚举不能再次设置特性的
obj.name = '书记';
console.log(obj.name); // undefined
for(var i in obj){
console.log(obj[i])
}
값: 속성 값
var obj = {}; Object.defineProperty(obj,'name',{ get:function(){} | undefined, set:function(){} | undefined, configuracble:true | false, enumerable:true | false }) 注意:当前使用了setter和getter方法;不允许使用writable和value两个属性
객체의 특정 속성을 설정하고 가져올 때 getter 및 setter 메서드를 제공할 수 있습니다.
var obj = {}; var value = 'xiangha'; Object.defineProperty(obj,'name',{ get:function(){ // 获取值触发 return value }, set:function(val){ // 设置值的时候触发;设置的新值通过参数val拿到 value = val; } }); console.log(obj.name); // xiangha obj.name = '书记'; console,.log(obj.name); // 书记
get과 set은 쌍으로 나타날 필요가 없습니다. ;set 및 get 메소드가 설정되지 않으면 정의되지 않습니다.Haha; vue를 사용하여 프로젝트를 개발합니다. 데이터 객체를 인쇄하려고 하면 데이터의 모든 속성에 get 및 set 속성 메서드가 있음을 알 수 있습니다. 다음은 vue와 각도 간의 양방향 데이터 바인딩 간의 차이점에 대한 설명입니다. 각도는 더티 데이터 감지를 사용합니다. 모델이 변경되면 모든 뷰가 관련 데이터에 바인딩되어 있는지 감지한 다음 뷰를 업데이트합니다.
Vue는 지점 간 바인딩 데이터
2.
<p id="app"> <form> <input type="text" v-model="number"> <button type="button" v-click="increment">增加</button> </form> <h3 v-bind="number"></h3> </p>
입력, v-model 명령 사용
a 버튼, v-click 명령 사용
var app = new xhVue({ el:'#app', data: { number: 0 }, methods: { increment: function() { this.number ++; }, } })
먼저 xhVue
function xhVue(options){ }
의 생성자를 정의해야 합니다. 이 생성자를 초기화하고 _init 속성을 추가합니다function xhVue(options){
this._init(options);
}
xhVue.prototype._init = function(options){
this.$options = options; // options为使用时传入的结构体;包括el,data,methods等
this.$el = document.querySelector(options.el); // el就是#app,this.$el是id为app的Element元素
this.$data = options.data; // this.$data = {number:0}
this.$methods = options.methods; // increment
}
_xhob 함수를 변환하고 프로세스 데이터를 다시 작성합니다.
指令类watcher;用来绑定更新函数;实现对DOM更新
function xhWatcher(name,el,vm,exp,attr){ this.name = name; // 指令名称;对于文本节点;例如text this.el = el; // 指令对应DOM元素 this.vm = vm; // 指令所属vue实例 this.exp = exp; // 指令对应的值;例如number this.attr = attr; // 绑定的属性值;例如innerHTML this.update(); } xhWatcher.prototype.update = function(){ this.el[this.attr] = this.vm.$data[this.exp]; // 例如h3的innerHTML = this.data.number;当numner改变则会触发本update方法;保证对应的DOM实时更新 }
2.5 完善_init和_xhob
继续完善_init和_xhob函数
// 给init的时候增加一个对象来存储model和view的映射关系;也就是我们前面定义的xhWatcher的实例;当model发生变化时;我们会触发其中的指令另其更新;保证了view也同时更新 xhVue.prototype._init = function(options){ this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods; this._binding = {}; // _binding this._xhob(this.$data); } // 通过init出来的_binding xhVue.prototype._xhob = function(obj){ // obj = {number:0} var value; for(key in obj){ if(obj.hasOwnProperty(ket)){ this._binding[key] = { // _binding = {number:_directives:[]} _directives = [] } value = obj[key]; if(typeof value === 'object'){ this._xhob(value); } var binding = this._binding[key]; Object.defineProperty(this.$data,key,{ enumerable:true, configurable:true, get:function(){ return value; }, set:function(newVal){ if(value !== newVal){ value = newVal; // 当number改变时;触发_binding[number]._directives中已绑定的xhWatcher更新 binding._directives.forEach(function(item){ item.update(); }); } } }) } } }
2.6 解析指令
怎么才能将view与model绑定;我们定义一个_xhcomplie函数来解析我们的指令(v-bind;v-model;v-clickde)并这这个过程中对view和model进行绑定
xhVue.prototype._xhcompile = function (root) { // root是id为app的element的元素;也就是根元素 var _this = this; var nodes = root.children; for (var i = 0,len = nodes.length; i < len; i++) { var node = nodes[i]; if (node.children.length) { // 所有元素进行处理 this._xhcompile(node) }; // 如果有v-click属性;我们监听他的click事件;触发increment事件,即number++ if (node.hasAttribute('v-click')) { node.onclick = (function () { var attrVal = nodes[i].getAttribute('v-click'); // bind让data的作用域与methods函数的作用域保持一致 return _this.$method[attrVal].bind(_this.$data); })(); }; // 如果有v-model属性;并且元素是input或者textrea;我们监听他的input事件 if (node.hasAttribute('v-model') && (node.tagName = 'INPUT' || node.tagName == 'TEXTAREA')) { node.addEventListener('input', (function (key) { var attrVal = node.getAttribute('v-model'); _this._binding[attrVal]._directives.push(new xhWatcher( 'input', node, _this, attrVal, 'value' )); return function () { // 让number的值和node的value保持一致;就实现了双向数据绑定 _this.$data[attrVal] = nodes[key].value } })(i)); }; // 如果有v-bind属性;我们要让node的值实时更新为data中number的值 if (node.hasAttribute('v-bind')) { var attrVal = node.getAttribute('v-bind'); _this._binding[attrVal]._directives.push(new xhWatcher( 'text', node, _this, attrVal, 'innerHTML' )) } } }
并且将解析函数也加到_init函数中
xhVue.prototype._init = function(options){ this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods; this._binding = {}; // _binding this._xhob(this.$data); this._xhcompile(this.$el); }
最后
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <p id="app"> <form> <input type="text" v-model="number"> <button type="button" v-click="increment">增加</button> </form> <h3 v-bind="number"></h3> </p> </body> <script> function xhVue(options) { this._init(options); } xhVue.prototype._init = function (options) { this.$options = options; this.$el = document.querySelector(options.el); this.$data = options.data; this.$method = options.methods; this._binding = {}; // _binding this._xhob(this.$data); this._xhcompile(this.$el); } xhVue.prototype._xhob = function (obj) { var value; for (key in obj) { if (obj.hasOwnProperty(key)) { this._binding[key] = { _directives: [] } value = obj[key]; if (typeof value === 'object') { this._xhob(value); } var binding = this._binding[key]; Object.defineProperty(this.$data, key, { enumerable: true, configurable: true, get: function () { console.log(`get${value}`) return value; }, set: function (newVal) { if (value !== newVal) { value = newVal; console.log(`set${newVal}`) // 当number改变时;触发_binding[number]._directives中已绑定的xhWatcher更新 binding._directives.forEach(function (item) { item.update(); }); } } }) } } } xhVue.prototype._xhcompile = function (root) { // root是id为app的element的元素;也就是根元素 var _this = this; var nodes = root.children; for (var i = 0, len = nodes.length; i < len; i++) { var node = nodes[i]; if (node.children.length) { // 所有元素进行处理 this._xhcompile(node) }; // 如果有v-click属性;我们监听他的click事件;触发increment事件,即number++ if (node.hasAttribute('v-click')) { node.onclick = (function () { var attrVal = node.getAttribute('v-click'); console.log(attrVal); // bind让data的作用域与method函数的作用域保持一致 return _this.$method[attrVal].bind(_this.$data); })(); }; // 如果有v-model属性;并且元素是input或者textrea;我们监听他的input事件 if (node.hasAttribute('v-model') && (node.tagName = 'INPUT' || node.tagName == 'TEXTAREA')) { node.addEventListener('input', (function (key) { var attrVal = node.getAttribute('v-model'); _this._binding[attrVal]._directives.push(new xhWatcher( 'input', node, _this, attrVal, 'value' )); return function () { // 让number的值和node的value保持一致;就实现了双向数据绑定 _this.$data[attrVal] = nodes[key].value } })(i)); }; // 如果有v-bind属性;我们要让node的值实时更新为data中number的值 if (node.hasAttribute('v-bind')) { var attrVal = node.getAttribute('v-bind'); _this._binding[attrVal]._directives.push(new xhWatcher( 'text', node, _this, attrVal, 'innerHTML' )) } } } function xhWatcher(name, el, vm, exp, attr) { this.name = name; // 指令名称;对于文本节点;例如text this.el = el; // 指令对应DOM元素 this.vm = vm; // 指令所属vue实例 this.exp = exp; // 指令对应的值;例如number this.attr = attr; // 绑定的属性值;例如innerHTML this.update(); } xhWatcher.prototype.update = function () { this.el[this.attr] = this.vm.$data[this.exp]; // 例如h3的innerHTML = this.data.number;当numner改变则会触发本update方法;保证对应的DOM实时更新 } var app = new xhVue({ el: '#app', data: { number: 0 }, methods: { increment: function () { this.number++; } } }); </script> </html>
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
위 내용은 vue의 DefineProperty 속성 사용의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!