我是靠谱客的博主 跳跃衬衫,最近开发中收集的这篇文章主要介绍Vue - (一) Vue中双向绑定的原理-Object.defineProperty,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Vue中双向绑定的原理是使用了Object.defineProperty进行绑定的。

我们先来看下官方给出的说法:

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

看一下Vue源码对于双向绑定的初期实现:

1. Even You 的初期定义(2013-07初次提交)

2. 在源码基础上进行了注释,注释的内容是个人理解,仅供参考。

<!DOCTYPE html>
<html>
	<head>
		<title>ideal</title>
		<meta charset="utf-8">
	</head>
	<body>
		<div id="test">
			<p>{{msg}}</p>
			<p>{{msg}}</p>
			<p>{{msg}}</p>
			<p>{{what}}</p>
			<p>{{hey}}</p>
		</div>
		<script>
			// span元素上绑定的自定义属性
			var bindingMark = 'data-element-binding';
			function Element (id, initData) {
				var self	 = this,
					// 当前绑定的ID元素,div id = test.
					el 		 = self.el = document.getElementById(id);
					// 需要绑定的span
					bindings = {} ;// the internal copy
					// 用于set的data
					data 	 = self.data = {}; // the external interface
					// 将{{mes}}转变成 <span data-element-binding='mes'></span>
					content  = el.innerHTML.replace(/{{(.*)}}/g, markToken);

				el.innerHTML = content;
				// 1.将页面上转换好的span移除额外样式,这是因为bindings已经绑定上对应的span了,没有那些样式也可以。
				// bindings[variable].els = el.querySelectorAll('[' + bindingMark + '="' + variable + '"]');
				for (var variable in bindings) {
					bind(variable);
				}
				// 2.触发Object.defineProperty的set,将值更改到span上。
				if (initData) {
					for (var variable in initData) {
						data[variable] = initData[variable]
					}
				}

				// 修改span标签样式
				function markToken (match, variable) {
					bindings[variable] = {};
					return '<span ' + bindingMark + '="' + variable +'"></span>'
				}

				function bind (variable) {
					// 绑定span
					bindings[variable].els = el.querySelectorAll('[' + bindingMark + '="' + variable + '"]');
					// 移除样式
					[].forEach.call(bindings[variable].els, function (e) {
				        e.removeAttribute(bindingMark)
				    });
					Object.defineProperty(data, variable, {
						set: function (newVal) {
						    [].forEach.call(bindings[variable].els, function (e) {
								e.textContent = newVal;
						        bindings[variable].value = newVal
						    })
						},
						get: function () {
						    return bindings[variable].value
						}
					})
				}

			}

			 new Element('test',{
				msg: 'hello',
				hey: 'hey'
			});

		</script>
	</body>
</html>

看一下Object.defineProperty的文档说明:

Object.defineProperty(obj, prop, descriptor)

 

obj
要在其上定义属性的对象。
prop
要定义或修改的属性的名称。
descriptor
将被定义或修改的属性描述符。

文档地址: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

基于Object.defineProperty实现一个类似的功能:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bindings</title>
</head>
<body>
    <span id="mes"></span>
    <span id="hello"></span>
</body>
</html>
<script>
    let initData = {
        mes: 'mes',
        hello: 'hello'
    };
    let spans = [];
    let data = {};
    function bind(key){
        Object.defineProperty(data ,key, {
            set: function (newValue) {
                spans[key].textContent = newValue;
                spans[key].value = newValue
            },
            get: function () {
                return spans[key].value;
            }
        });
    };
    // 绑定span
    for (let dataKey in initData) {
        spans[dataKey] = document.getElementById(dataKey);
        bind(dataKey);
    }

    // 触发set
    for (let dataKey in initData) {
        data[dataKey] = initData[dataKey];
    }

</script>

 

最后

以上就是跳跃衬衫为你收集整理的Vue - (一) Vue中双向绑定的原理-Object.defineProperty的全部内容,希望文章能够帮你解决Vue - (一) Vue中双向绑定的原理-Object.defineProperty所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部