五十行javascript代码实现简单的双向数据绑定
五十行javascript代码实现简单的双向数据绑定
Vue框架想必从事前端开发的同学都使用过,它的双向数据绑定机制能给我们带来很大的方便。今天闲着没事,尝试着实现一下双向数据绑定,接下来给大家分享一下。
Object.defineProperty(obj, prop, descriptor)
Object.defineProperty
方法允许精确添加或修改对象的属性。它的第一个参数 obj
是要在其上定义属性的对象,第二个参数 prop
是要定义或修改的属性的名称,第三个参数 descriptor
是一个将被定义或修改的属性的描述符。
返回值: 被传递给函数的对象。
来举个例子:
var o = Object.defineProperty({}, 'name', {
value: 1
});
console.log(o) // {name: 1}
这是最基本的定义一个对象的方式。对于属性描述符,还有很多其他属性:
数据描述符和存取描述符均具有以下可选键值:
configurable
当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false。enumerable
当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false。
数据描述符同时具有以下可选键值:
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。writable
当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。
存取描述符同时具有以下可选键值:
get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给属性。默认为 undefined。
这里只说一下 get
和 set
:
看一下这个例子:
var o = Object.defineProperty({}, 'name', {
get: function () {
return this._name_;
},
set: function (value) {
this._name_ = value * 2;
}
});
o.name = 1;
console.log(o.name); // 2
给属性 name
定义了一个 get
和 set
,为什么使用 _name_
而不是name
呢?因为name
是正在被定义的属性,如果在get
或者set
中使用name
无形之中就会发生递归,导致栈溢出。_name_
这个是自己自定义的,你完全可以设置为$name
、__name__
等等。
另外,使用对象的字面量形式也可以设置get
与set
:
var o = {
get name(){
return this._name_;
},
set name(value){
this._name_ = value * 2;
}
};
o.name = 1;
console.log(o.name); // 2
实现双向数据绑定
要实现双向数据绑定,肯定要从 get
与 set
下手,在 set
的函数中重新渲染相关的数据,所以一开始应该是这样的:
var o = {
get name(){
return this._name_;
},
set name(value){
this._name_ = value;
this.render('name');
},
render: function(pro){
document.write(this[pro]);
}
};
在浏览器控制台修改一下o.name
试试:
如何实现表单控件到数据的绑定呢?在 Vue
中,表单元素通过 v-model
绑定一个变量,类型这样:
<input type="text" v-model="name">
其实 v-model
的元素是绑定了一个 input
的自定义事件,我们不考虑那么多,就使用原生的 oninput
事件来模拟下。
var o = {
get name(){
return this._name_;
},
set name(value){
this._name_ = value;
console.log(this._name_);
},
inputInit: function () {
var self = this;
var vModels = document.querySelectorAll('[v-model]');
for (let i = 0; i < vModels.length; i++) {
vModels[i].addEventListener('input', function () {
var property = this.getAttribute('v-model');
var value = this.value;
self.name = value;
})
}
}
}.inputInit();
至此一个简单的双向数据绑定就差不多了,我们模仿一下 Vue
的api格式,再将代码封装一下:
html:
<input type="text" v-model="name">
<p v-text="name"></p>
javascript:
function Vue(options) {
var data = options.data || {};
var dKeys = Object.keys(data);
var _this = this;
this.vData = {};
// 根据data中的变量数量动态的绑定 get 与 set
for (let i = 0; i < dKeys.length; i++) {
Object.defineProperty(this.vData, dKeys[i], {
get: function () {
return this['__' + dKeys[i] + '__'];
},
set: function (value) {
this['__' + dKeys[i] + '__'] = value;
_this.render(dKeys[i]); // 重新渲染相关数据
}
})
}
for(let i in data) { // 初始化时设置一变vData,触发一遍 set
this.vData[i] = data[i];
}
this.inputInit(); // 给表单组件绑定事件监听
}
Vue.prototype.render = function (pro) {
var vModels = document.querySelectorAll('[v-model=' + pro + ']');
var vText = document.querySelectorAll('[v-text=' + pro + ']');
for (var i = 0; i < vModels.length; i++) {
vModels[i].value = this.vData[pro];
}
for (var j = 0; j < vText.length; j++) {
vText[j].innerText = this.vData[pro];
}
};
Vue.prototype.inputInit = function () {
var self = this;
var vModels = document.querySelectorAll('[v-model]');
for (let i = 0; i < vModels.length; i++) {
vModels[i].addEventListener('input', function () {
var property = this.getAttribute('v-model');
var value = this.value;
self.vData[property] = value;
})
}
};
var vm = new Vue({
data: {
name: 1
}
})
五十行javascript代码实现简单的双向数据绑定的更多相关文章
- JavaScript实现简单的双向数据绑定
什么是双向数据绑定 双向数据绑定简单来说就是UI视图(View)与数据(Model)相互绑定在一起,当数据改变之后相应的UI视图也同步改变.反之,当UI视图改变之后相应的数据也同步改变. 双向数据绑定 ...
- 利用ES6中的Proxy和Reflect 实现简单的双向数据绑定
利用ES6中的Proxy (代理) 和 Reflect 实现一个简单的双向数据绑定demo. 好像vue3也把 obj.defineProperty() 换成了Proxy+Reflect. 话不多说 ...
- React简单实现双向数据绑定
import React, { Component } from 'react' import ReactDOM from 'react-dom' class App extends Componen ...
- javascript代码实现简单的五星评价功能!
<script type="text/javascript"> //★ var spans=document.getElementsByTagName("sp ...
- 自己手动实现简单的双向数据绑定 mvvm
数据绑定 数据绑定一般就是指的 将数据 展示到 视图上.目前前端的框架都是使用的mvvm模式实现双绑的.大体上有以下几种方式: 发布订阅 ng的脏检查 数据劫持 vue的话采用的是数据劫持和发布订阅相 ...
- 原生js简单实现双向数据绑定原理
根据对象的访问器属性去监听对象属性的变化,访问器属性不能直接在对象中设置,而必须通过 defineProperty() 方法单独定义. 访问器属性的"值"比较特殊,读取或设置访问器 ...
- 简单实现双向数据绑定mvvm。
- angularJs初体验,实现双向数据绑定!使用体会:比较爽
使用初体验:ng 双向数据绑定: 最简单的双向数据绑定:(使用默认模块控制) <body ng-app> <input type="text" ng-model= ...
- 深入vue源码,了解vue的双向数据绑定原理
大家都知道vue是一种MVVM开发模式,数据驱动视图的前端框架,并且内部已经实现了双向数据绑定,那么双向数据绑定是怎么实现的呢? 先手动撸一个最最最简单的双向数据绑定 <div> < ...
随机推荐
- 基于 Koa平台Node.js开发的KoaHub.js获取/设置会话功能代码
koa-session2 Middleware for Koa2 to get/set session use with custom stores such as Redis or mongodb ...
- 算法模板——平衡树Treap
实现功能如下——1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大 ...
- ASP.NET Core MVC 源码学习:Routing 路由
前言 最近打算抽时间看一下 ASP.NET Core MVC 的源码,特此把自己学习到的内容记录下来,也算是做个笔记吧. 路由作为 MVC 的基本部分,所以在学习 MVC 的其他源码之前还是先学习一下 ...
- Linux关机重启指令
关机: init 0 [使用Linux的运行级别] halt poweroff shutdown -h [系统会发出广播信息,显示即将关机时间] shutdown -c [取消关机计划] 重启: r ...
- boost.asio源码阅读(2) - task_io_service
1.0 task_io_service 在boost.asio源码阅读(1)中,代码已经查看到task_io_service中. 具体的操作调用void task_io_service::init_t ...
- 把GIF背景变透明
准备软件: 1.Ps cs4 2.QuickTime Player 7.74 开始: 1. 2.弹出文件选择框,但是发现不能选择GIF格式. 3.没关系,在文件名框输入*.*回车,就发现可以选择GIF ...
- CSS3 transition 浏览器兼容性
1.兼容性 根据canius(http://caniuse.com/#search=transition),transition 兼容性如下图所示: <!DOCTYPE html> < ...
- css删除线,下划线等
<style> .p1 { text-decoration:overline; //上划线 } .p2 { text-decoration:line-through; //删除线 } . ...
- DBProxy 入门到精通系列(二):DBProxy快速入门教程
这里主要用来了解有关DBProxy方面的部署及基本的配置,以及模拟架构 1 DBProxy方面的安装部署 1)基础环境的部署 # .x86_64 Percona-Server-client-.x86_ ...
- express创建网站
Express 在初始化一个项目的时候需要指定模板引擎,默认支持Jade和ejs. 这里我们使用ejs模板引擎:(关于ejs的介绍可以先从百科里面了解一个大概)EJS是一个JavaScript模板库, ...