当前位置: 首页 > news >正文

深圳网站建设制作设计企业2024年新冠疫情最新消息

深圳网站建设制作设计企业,2024年新冠疫情最新消息,h5页面制作工具包括,wordpress 播放大视频项目地址:https://github.com/jrainlau/mog在线体验:http://codepen.io/jrainlau/pe...作为一个前端开发者,曾踩了太多的“数据绑定”的坑。在早些时候,都是通过jQuery之类的工具手动完成这些功能,但是当数据量非常大的…

项目地址:https://github.com/jrainlau/mog
在线体验:
http://codepen.io/jrainlau/pe...


作为一个前端开发者,曾踩了太多的“数据绑定”的坑。在早些时候,都是通过jQuery之类的工具手动完成这些功能,但是当数据量非常大的时候,这些手动的工作让我非常痛苦。直到使用了VueJS,这些痛苦才得以终结。

VueJS的其中一个卖点,就是“数据绑定”。使用者无需关心数据是怎么绑定到dom上面的,只需要关注数据就好,因为VueJS已经自动帮我们完成了这些工作。

这真的非常神奇,我不可救药地爱上了VueJS,并且把它用到我自己的项目当中。随着使用的深入,我更加想知道它深入的原理是什么。

VueJS是如何进行数据绑定的?

通过阅读官方文档,我看到了下面这段话:

把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。

关键词是Object.definProperty,在MDN文档里面是这么说的:

Object.defineProperty()方法直接定义一个对象的属性,或者修改对象当中一个已经存在的属性,并返回这个对象。

让我们写个例子来测试一下它。

首先,建立一个钢铁侠对象并赋予他一些属性:

let ironman = {name: 'Tony Stark',sex: 'male',age: '35'
}

现在我们使用Object.defineProperty()方法来对他的一些属性进行修改,并且在控制台把所修改的内容输出:

Object.defineProperty(ironman, 'age', {set (val) {console.log(`Set age to ${val}`)return val}
})ironman.age = '48'
// --> Set age to 48

看起来挺完美的。如果把console.log('Set age to ${val}')改为element.innerHTML = val,是不是就意味着数据绑定已经完成了呢?

让我们再修改一下钢铁侠的属性:

let ironman = {name: 'Tony Stark',sex: 'male',age: '35',hobbies: ['girl', 'money', 'game']
}

嗯……他就是一个花花公子。现在我想把一些“爱好”添加到他身上,并且在控制台看到对应的输出:

Object.defineProperty(ironman.hobbies, 'push', {value () {console.log(`Push ${arguments[0]} to ${this}`)this[this.length] = arguments[0]}
})ironman.hobbies.push('wine')
console.log(ironman.hobbies)// --> Push wine to girl,money,game
// --> [ 'girl', 'money', 'game', 'wine' ]

在此之前,我是使用get()方法去追踪对象的属性变化,但是对于一个数组,我们不能使用这个方法,而是使用value()方法来代替。虽然这招也灵,但是并非最好的办法。有没有更好的方法可以简化这些追踪对象或数组属性变化的方法呢?

在ECMA2015,Proxy是一个不错的选择

什么是Proxy?在MDN文档中是这么说的(误):

Proxy可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

Proxy是ECMA2015的一个新特性,它非常强大,但我并不会讨论太多关于它的东西,除了我们现在需要的一个。现在让我们一起来新建一个Proxy实例:

let ironmanProxy = new Proxy(ironman, {set (target, property, value) {target[property] = valueconsole.log('change....')return true}
})ironmanProxy.age = '48'
console.log(ironman.age)// --> change....
// --> 48

符合预期。那么对于数组呢?

let ironmanProxy = new Proxy(ironman.hobbies, {set (target, property, value) {target[property] = valueconsole.log('change....')return true}
})ironmanProxy.push('wine')
console.log(ironman.hobbies)// --> change...
// --> change...
// --> [ 'girl', 'money', 'game', 'wine' ]

仍然符合预期!但是为什么输出了两次change...呢?因为每当我触发push()方法的时候,这个数组的length属性和body内容都被修改了,所以会引起两次变化。

实时数据绑定

解决了最核心的问题,可以考虑其他的问题了。

想象一下,我们有一个模板和数据对象:

<!-- html template -->
<p>Hello, my name is {{name}}, I enjoy eatting {{hobbies.food}}</p><!-- javascript -->
let ironman = {name: 'Tony Stark',sex: 'male',age: '35',hobbies: {food: 'banana',drink: 'wine'}
}

通过前面的代码,我们知道如果想要追踪一个对象的属性变化,我们应该把这个属性作为第一个参数传入Proxy实例。让我们一起来创建一个返回新的Proxy实例的函数吧!

function $setData (dataObj, fn) {let self = thislet once = falselet $d = new Proxy(dataObj, {set (target, property, value) {if (!once) {target[property] = valueonce = true/* Do something here */}return true}})fn($d)}

它可以通过以下的方式被使用:

$setData(dataObj, ($d) => {/* * dataObj.someProps = something*/
})// 或者$setData(dataObj.arrayProps, ($d) => {/* * dataObj.push(something)*/
})

除此之外,我们应该实现模板对数据对象的映射,这样才能用Tony Stark来替换{{name}}

function replaceFun(str, data) {let self = thisreturn str.replace(/{{([^{}]*)}}/g, (a, b) => {return data[b]})}replaceFun('My name is {{name}}', { name: 'xxx' })
// --> My name is xxx

这个函数对于如{ name: 'xx', age: 18 }的单层属性对象运行良好,但是对于如{ hobbies: { food: 'apple', drink: 'milk' } }这样的多层属性对象却无能为力。举个例子,如果模板关键字是{{hobbies.food}},那么replaceFun()函数就应该返回data['hobbies']['food']

为了解决这个问题,再来一个函数:

function getObjProp (obj, propsName) {let propsArr = propsName.split('.')function rec(o, pName) {if (!o[pName] instanceof Array && o[pName] instanceof Object) {return rec(o[pName], propsArr.shift())}return o[pName]}return rec(obj, propsArr.shift())}getObjProp({ data: { hobbies: { food: 'apple', drink: 'milk' } } }, 'hobbies.food')
// --> return  { food: 'apple', drink: 'milk' }

最终的replaceFun()函数应该是下面这样子的:

function replaceFun(str, data) {let self = thisreturn str.replace(/{{([^{}]*)}}/g, (a, b) => {let r = self._getObjProp(data, b);console.log(a, b, r)if (typeof r === 'string' || typeof r === 'number') {return r} else {return self._getObjProp(r, b.split('.')[1])}})}

一个数据绑定的实例,叫做“Mog”

不为什么,就叫做“Mog”。

class Mog {constructor (options) {this.$data = options.datathis.$el = options.elthis.$tpl = options.templatethis._render(this.$tpl, this.$data)}$setData (dataObj, fn) {let self = thislet once = falselet $d = new Proxy(dataObj, {set (target, property, value) {if (!once) {target[property] = valueonce = trueself._render(self.$tpl, self.$data)}return true}})fn($d)}_render (tplString, data) {document.querySelector(this.$el).innerHTML = this._replaceFun(tplString, data)}_replaceFun(str, data) {let self = thisreturn str.replace(/{{([^{}]*)}}/g, (a, b) => {let r = self._getObjProp(data, b);console.log(a, b, r)if (typeof r === 'string' || typeof r === 'number') {return r} else {return self._getObjProp(r, b.split('.')[1])}})}_getObjProp (obj, propsName) {let propsArr = propsName.split('.')function rec(o, pName) {if (!o[pName] instanceof Array && o[pName] instanceof Object) {return rec(o[pName], propsArr.shift())}return o[pName]}return rec(obj, propsArr.shift())}}

使用:

<!-- html --><div id="app"><p>Hello everyone, my name is <span>{{name}}</span>, I am a mini <span>{{lang}}</span> framework for just <span>{{work}}</span>. I can bind data from <span>{{supports.0}}</span>, <span>{{supports.1}}</span> and <span>{{supports.2}}</span>. What's more, I was created by <span>{{info.author}}</span>, and was written in <span>{{info.jsVersion}}</span>. My motto is "<span>{{motto}}</span>".</p></div><div id="input-wrapper">Motto: <input type="text" id="set-motto" autofocus></div>
<!-- javascript -->let template = document.querySelector('#app').innerHTMLlet mog = new Mog({template: template,el: '#app',data: {name: 'mog',lang: 'javascript',work: 'data binding',supports: ['String', 'Array', 'Object'],info: {author: 'Jrain',jsVersion: 'Ecma2015'},motto: 'Every dog has his day'}
})document.querySelector('#set-motto').oninput = (e) => {mog.$setData(mog.$data, ($d) => {$d.motto = e.target.value})
}

你可以在这里进行在线体验。

后记

Mog仅仅是一个用于学习数据绑定的实验性质的项目,代码仍然不够优雅,功能也不够丰富。但是这个小玩具让我学习了很多。如果你对它有兴趣,欢迎到这里把项目fork走,并且加入一些你的想法。

感谢阅读!

http://www.lbrq.cn/news/2800675.html

相关文章:

  • 全国政府网站建设情况网络优化培训
  • 1688货源网外发手工加工快速优化seo软件
  • 建设银行官方网站下载群排名优化软件
  • wordpress更改密码seo平台是什么意思
  • 哪些公司网站推广能赚钱代发新闻稿的网站
  • 网页网站制作维护商丘seo教程
  • 做网站公司排名电话it行业培训机构哪个好
  • 网站建设域名是什么意思推广策略及推广方式
  • 做网站太麻烦了百度科技有限公司
  • 网页设计期末作品要求小红书怎么做关键词排名优化
  • php做的网站处理速度怎么样营销推广的公司
  • 站长工具seo客户端佛山快速排名seo
  • 上海网站开发开发好的公司北京百度竞价托管公司
  • 网站必须做公安备案么互联网营销工具有哪些
  • 秦皇岛做网站外包360浏览器网页版入口
  • 做ppt配图好用的网站高佣金app软件推广平台
  • bootstrap公司网站百度品牌
  • 三亚建设局网站河南seo技术教程
  • 怎么让自己做的网站让别人看到百度指数是怎么计算的
  • 头像网站模板baidu百度首页官网
  • 160;作者:网站建设&自己建站的网站
  • 专业做网站的人网络营销推广渠道有哪些
  • 导航网站 黄色托管竞价账户哪家好
  • 可视化网站开发系统介绍电子商务网络营销
  • 购物网站 后台近10天的时政新闻
  • 做外贸需要浏览外国网站商品促销活动策划方案
  • 湖南益阳网站建设网络营销主要有哪些特点
  • 购物网站模板 php如何进行搜索引擎优化?
  • 动漫设计需要学什么关键词优化排名要多少钱
  • 建设工程合同的内容北京专门做seo
  • 【力扣 Hot100】滑动窗口巧解字串问题
  • 与森马品牌代言人王安宇专注日常力量,再启新常服故事
  • 训练后数据集后部署PaddleOCR转trt流程
  • 【嵌入式电机控制#34】FOC:意法电控驱动层源码解析——HALL传感器中断(不在两大中断内,但重要)
  • 8 webUI中-Controlnet(控制与约束)的应用分类与使用方法
  • Temu美国站大规模扫号封店:虚假本土店遭批量封禁,如何规避?