Object.defineProperties()
w
https://docs.microsoft.com/en-us/scripting/javascript/reference/object-defineproperty-function-javascript
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties
双向绑定
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Document</title>
</head>
<body>
<div id="app">
<form>
<input type="text" v-model="count"/>
<button type="button" v-click="increment">increment</button>
<button type="button" v-click="alert('Hello world')">alert</button>
</form>
<p v-bind="count"></p>
</div>
<script>
function Lue(options) {
this._init(options);
console.log(this)
} Lue.prototype._init = function (options) {
this.$options = options; //传入的实例配置
this.$el = document.querySelector(options.el); //实例绑定的根节点
this.$data = options.data; //实例的数据域
this.$methods = options.methods; //实例的函数域 //与DOM绑定的数据对象集合
//每个成员属性有一个名为_directives的数组,用于在数据更新时触发更新DOM的各directive
this._binding = {};
this._parseData(this.$data); this._compile(this.$el); //编译DOM节点
}; //遍历数据域,添加getter/setter
Lue.prototype._parseData = function (obj) {
var value;
for (var key in obj) {
//排除原型链上的属性,仅仅遍历对象本身拥有的属性
if (obj.hasOwnProperty(key)) {
this._binding[key] = { //初始化与DOM绑定的数据对象
_directives: []
};
value = obj[key];
this.convert(key, value);
}
}
}; /**对象属性重定义
* @param key 数据对象名称,本例为"count"
* @param val 数据对象的值
*/
Lue.prototype.convert = function (key, val) {
var binding = this._binding[key];
Object.defineProperty(this.$data, key, {
enumerable: true,
configurable: true,
get: function () {
console.log(`获取$
{
val
}`)
;
return val;
},
set: function (newVal) {
console.log(`更新$
{
newVal
}`)
;
if (val != newVal) {
val = newVal;
binding._directives.forEach(function (item) {
item.update();
})
}
}
})
}; function Directive(name, el, vm, exp, attr) {
this.name = name; //指令名称,例如文本节点,该值设为"text"
this.el = el; //指令对应的DOM元素
this.vm = vm; //指令所属lue实例
this.exp = exp; //指令对应的值,本例如"count"
this.attr = attr; //绑定的属性值,本例仅实验innerHTML this.update(); //首次绑定时更新
} Directive.prototype.update = function () {
//更新DOM节点的相应属性值
this.el[this.attr] = this.vm.$data[this.exp];
}; //解析DOM的指令
Lue.prototype._compile = function (root) {
var _this = this;
//获取指定作用域下的所有子节点
var nodes = root.children;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
//若该元素有子节点,则先递归编译其子节点
if (node.children.length) {
this._compile(node);
} if (node.hasAttribute("v-click")) {
node.onclick = (function () {
var attrVal = nodes[i].getAttribute("v-click");
var args = /\(.*\)/.exec(attrVal);
if (args) { //如果函数带参数,将参数字符串转换为参数数组
args = args[0];
attrVal = attrVal.replace(args, "");
args = args.replace(/[\(|\)|\'|\"]/g, '').split(",");
}
else args = [];
return function () {
_this.$methods[attrVal].apply(_this.$data, args);
}
})()
} if (node.hasAttribute(("v-model"))
&& node.tagName == "INPUT" || node.tagName == "TEXTAREA") {
//如果是input或textarea标签
node.addEventListener("input", (function (key) {
var attrVal = node.getAttribute("v-model");
//将value值的更新指令添加至_directives数
_this._binding[attrVal]._directives.push(new Directive(
"input",
node,
_this,
attrVal,
"value"
)) return function () {
_this.$data[attrVal] = nodes[key].value;
}
})(i));
} if (node.hasAttribute("v-bind")) {
var attrVal = node.getAttribute("v-bind");
//将innerHTML的更新指令添加至_directives数
_this._binding[attrVal]._directives.push(new Directive(
"text",
node,
_this,
attrVal,
"innerHTML"
))
}
}
} window.onload = function () {
var app = new Lue({
el: "#app",
data: {
count: 0,
},
methods: {
increment: function () {
this.count++;
},
alert: function (msg) {
alert(msg)
}
}
})
}
</script>
</body>
</html>
Object.defineProperties()的更多相关文章
- 分享一个Object.defineProperties 定义一个在原对象可读可写的方法
function A(){ this.name = 'hellow word'; } Object.defineProperties( A.prototype,{ doSomething2 : { v ...
- Object.defineProperties()和Object.defineProperty()方法
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象. 语法:Object.defineProperty(obj, pro ...
- JS Object.defineProperties()方法
JS Object.defineProperties()方法 描述: Object.defineProperties()方法为目标对象同时配置多个属性. 语法: Object.defineProper ...
- Object.defineProperties()与Proxy对象代理
Object.defineProperties() 了不起啊..vue.js通过它实现双向绑定的 Object.defineProperties(obj,props) 方法直接在一个对象上定义新的属性 ...
- Object.defineProperty和Object.defineProperties
添加属性到对象,或修改现有属性的特性 用法: Object.defineProperty(object, propertyName, descriptor); 参数: object ...
- Object.defineProperties——MEAN开发后台的Model层
Object.defineProperties是什么?有什么用? 这个问题比较听起来可能比较难以理解,确实我也是在项目中遇到的才会去想.以前看到<高级程序设计>的时候,有这么一种东西,定义 ...
- 定义多个属性 Object.defineProperties()
var book = {} Object.defineProperties(book,{ _year:{ value:2004 }, editable:{ value:1 }, year:{ get: ...
- js中Object.defineProperties 定义一个在原对象可读可写的方法
function A(){ this.name = 'hellow word'; } Object.defineProperties( A.prototype,{ doSomething2 : { v ...
- ES5 Object.defineProperties / Object.defineProperty 的使用
临时笔记,稍后整理 var obj = { v: , render: function () { console.log(") } }; // Object.defineProperties ...
随机推荐
- Android-RelativeLayout布局技巧(一)
如果有一个需求是这样的,在标题中的右上角有一个button <?xml version="1.0" encoding="utf-8"?> <L ...
- Oracle,跳出游标循环
1,跳出游标的循环,不执行遍历了. 方法一:goto for c_row in 游标 loop if 条件 then dbms_output.put_line('测试跳出循环'); goto brea ...
- ingress高可用--使用DaemonSet方式部署ingress-nginx
前言 为了配置kubernetes中的ingress的高可用,对于kubernetes集群以外只暴露一个访问入口,需要使用keepalived排除单点问题.需要使用daemonset方式将ingres ...
- iOS活体人脸识别的Demo和一些思路
代码地址如下:http://www.demodashi.com/demo/12011.html 之前公司项目需要,研究了一下人脸识别和活体识别,并运用免费的讯飞人脸识别,在其基础上做了二次开发,添加了 ...
- androidstudio新建项目中在布局文件中不显示title的方法
在androidstudio新建项目的时候,在布局文件里有时候会出现如下情况: 上面的标题栏非常碍眼,要想隐藏标题栏的话,可以在Manifest文件的theme标签里进行配置,自定义一个theme,加 ...
- json2.js
/* http://www.JSON.org/json2.js 2010-03-20 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT Y ...
- SpringCloud系列八:自定义Ribbon配置
1. 回顾 上文使用Ribbon实现了客户端侧的负载均衡.但是很多场景下,我们可能需要自定义Ribbon的配置,比如修改Ribbon的负载均衡规则. Spring Cloud允许使用Java代码或属性 ...
- leetCode 30.Substring with Concatenation of All Words (words中全部子串相连) 解题思路和方法
Substring with Concatenation of All Words You are given a string, s, and a list of words, words, tha ...
- android launcher2开发之 有抽屉改成无抽屉
在launcher.java中在createShortcut方法中 屏蔽全部应用button 修改之前 View createShortcut(int layoutResId, ViewGroup ...
- Lua顺序 执行顺序
1.4.2. Lua顺序 Nginx下Lua处理阶段与使用范围: init_by_lua http set_by_lua server, server if, location, location i ...