如果说,vue、react是自动档,那么jQuery就是手动挡。自动挡虽然好开,但是总是缺少那么点乐趣,手动挡虽然慢慢被替代,不过自然有其独有的味道。如果,设想一下有这么一个中间产品,半自动档,会不会让老车焕发第二春?
先上一段代码片段
选择的瓜是:
// 制作一个数据绑定形式
let observer = (() => {// 换成数据绑定的形式const genEventName = (id, key) => {return [id, key].join('_');}const notify = (id, key, newVal, oldVal) => {let notifyEvent = new CustomEvent(genEventName(id, key), {detail: [newVal, oldVal]});document.dispatchEvent(notifyEvent);}const bindEvent = (id, key, callback) => {document.addEventListener(genEventName(id, key), callback)}const create = (newObject, data) => {for (let key in data) {let value = data[key];Object.defineProperty(newObject, key, {get() {return value},set(newVal) {if (newVal !== value) {let oldVal = value;value = newVal;notify(this.__uuid, key, newVal, oldVal);}}})}}return function (data) {let newObject = Object.create(null);// 假设生成一个不重复的idlet __uuid = parseInt(Math.random() * 1e5);newObject.__uuid = __uuid;return {on(keyname, callback) {if (typeof callback === 'function')bindEvent(newObject.__uuid, keyname, (e) => callback.apply(newObject, e.detail));return this;},create(callback) {create(newObject, data);if (typeof callback == 'function') {callback.call(newObject, newObject);}return newObject;}}}
})();
现代浏览器下可以使用Proxy代理对象,通过中间人访问元数据,而这里使用重建新对象的形式。无论是proxy还是重建对象,都是对元数据的代理行为,不会修改元数据。
要操作一个数据的访问和设置,首先要知道数据什么时候被更新和获取,然后通过控制中间环节,可以很好的处理此间的行为,把真是的数据隐藏起来,这算是设计模式中的代理模式了。
本文中的数据劫持在create(newObject, data);
完成,通过Object.defineProperty
完成对元数据的key拷贝,这样,就有一份一比一key对应的数据对象了,后续的操作都通过本对象进行操作。
当需求是,设置某个数据后,操作某个数据的变更结果。那通过什么形式实现呢?
dom操作上一个很重要的方式就是事件,比如click、change,那如果使用一个自定义的过程,模仿click、change会如何?
const genEventName = (id, key) => {return [id, key].join('_');
}
const notify = (id, key, newVal, oldVal) => {let notifyEvent = new CustomEvent(genEventName(id, key), {detail: [newVal, oldVal]});document.dispatchEvent(notifyEvent);
}
const bindEvent = (id, key, callback) => {document.addEventListener(genEventName(id, key), callback)
}
使用document.addEventListener
监听事件,该事件可以是click、touchmove、也可以是a、b、c。使用此特性,可以构建一个不重复的事件,然后在某个时刻触发该事件,则有了以下的事件构建形式:
let newObject = Object.create(null);
// 假设生成一个不重复的id
let __uuid = parseInt(Math.random() * 1e5);
newObject.__uuid = __uuid;
return {on(keyname, callback) { if (typeof callback === 'function')bindEvent(newObject.__uuid, keyname, (e) => callback.apply(newObject, e.detail)); return this;},
}
且在数据 data.key = newvalue
时,触发此事件即完成的事件闭环
Object.defineProperty(newObject, key, {set(newVal) {if (newVal !== value) {let oldVal = value;value = newVal;// 数据变化通知事件notify(this.__uuid, key, newVal, oldVal);}}
}
则流程为
graph TD
数据绑定 --> 主动key监听--> value变更-->事件通知
选择的瓜是:
let data = observer({ list: [], choose: ""});
// 当list被修改时,更新html的内容
data.on('list', (newList, oldList) => {let allList = newList.map((text) => $('').text(text));$('ul.home').empty().append(allList);
});
// 当choose被更新时,修改choose的文本
data.on('choose',(choose)=> $('#choose').text(choose))
// 创建整个监听结果
data.create(function onMounted(newObject) {$('ul.home').on('click', 'li', ({ target, delegateTarget }) => {let { classes } = $(delegateTarget).data()let name = $(target).text()// 当点击li时,修改choose的数据newObject.choose = [classes, name];});// 修改list的数据newObject.list = ["男人", '女人', '小孩', '狗', '家']
});
- {{text}}
选择的瓜是:{{choose}}
new Vue {app:"#app"data:{list:[],classes:"家"choose:""},methods:{liClick(text){this.choose = [this.$refs.home.dataset.classes,text]}},mounted(){this.list = ["男人", '女人', '小孩', '狗', '家'];}
}
代码很清爽,大量的重复工作——监听、绑定、dom更新,都在不知不觉中完成,如果换车这种形式:
选择的瓜是:
let data = observer('#app',{ list: [], choose: ""}).chooseClick(function(text){this.choose = text;})
// 创建整个监听结果
data.create(function onMounted(newObject) {// 修改list的数据newObject.list = ["男人", '女人', '小孩', '狗', '家']
});
jQuery对作者而言,和jsp一样,就是青春。而现在mvvm的基础框架上,对前端的发展是一个很大的突破,让代码的结构更清晰。jQuery在历史的长河中,也贡献了很多设计思想,比如$()
之document.querySelector()
。但是时代总要向前,也会不久的将来也会像怀念jQuery一样怀念vue、react…
最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。
有需要的小伙伴,可以点击下方卡片领取,无偿分享