作为一名后端,一直想不通Vue的动态渲染机制,直到逛度娘遇到了 Object.defineProperty,然后各种想法促使我去实操就有了这篇笔记(我只是一名萌新,勿喷)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js简单实现Vue2动态渲染</title>
</head>
<body>
<div id="test"></div>
<script src="http://itphy.com/cdn/jquery/jquery.js"></script>
<script>
function bindDom(obj,domObj,config){
for (let field in config) {
let cField=config[field],objField=obj[field];
Object.defineProperty(obj,field,{
set:function (v) {
console.log('数据拦截')
if(v instanceof Array){
const aryMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
//console.log("数组初始化")
aryMethods.forEach((method)=> {
let original = Array.prototype[method];
v[method] = function () {
let result=original.apply(this, arguments);
// console.log("数组赋值-方法操作")
cField.set(objField=this,domObj);
return result;
};
});
}
/**
* v 新值
* domObj: dom元素
* */
// console.log("数组赋值-引用替换")
typeof (cField.set)=='function'?cField.set(objField=v,domObj):{};
},
get:function () {
/**
* domObj: dom元素
* objField: 字段现有值
*/
return typeof (cField.get)=='function'?cField.get(objField,domObj):objField;
},
});
}
}
let div_p={
$this: document.getElementById("test"),
data:{
list:[]
},
init: function (){
bindDom(this.data,this.$this,{
list:{
set:function (v,dom){
$(dom).empty();
if(v instanceof Array ){
$(v).each((i,t)=>{
$(dom).append($('<p></p>').html(t)[0])
})
}
}
}
})
return this.data;
}
}
let o=div_p.init();
let a=['1','2','3']
o.list=a
console.log("你可以通过在控制台输入 o.list.push('4') 或者 o.list=['哈哈哈','小意思'] \n 来动态渲染页面dom元素");
</script>
</body>
</html>
优化版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js vue</title>
<link rel="stylesheet" href="http://itphy.com/cdn/select2/css/select2.css" >
</head>
<body>
<div id="app">
</div>
<script src="http://itphy.com/cdn/jquery/jquery.js"></script>
<script src="http://itphy.com/cdn/select2/js/select2.js"></script>
<script>
(function ($) {
$.fn.extend({
cache: new Map(),
bind: function (data,view) {
debugger
this.objBind(data,false,view);
return data;
},
objBind: function (data, fParent,view,i) {
let $this = this, cache = this.cache;
!fParent?cache.set("data",data):1==1;
for (let f in data) {
let fv=data[f];
Object.defineProperty(data, f, {
get: function () {
return fv;
},
set: function (v) {
fv=v;
(typeof (view) == 'function' )? view(cache.get("data"),$this[0]):1==1;
}
});
if (fv instanceof Array) {
debugger
this.arrayBind(fv,fParent?fParent:f,view)
continue ;
}
if (fv instanceof Object ) {
this.objBind(fv, fParent?fParent:f,view);
continue ;
}
}
},
arrayBind: function (data,fParent,view){
let $this = this, cache = this.cache;
const aryMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
aryMethods.forEach((method) => {
let original = Array.prototype[method];
data[method] = function () {
let result = original.apply(this, arguments);
typeof (view)=='function' ? view(cache.get("data"),$this[0]):1==1;
return result;
};
});
data.forEach((t,i)=> {
if(t instanceof Array){
$this.arrayBind(t,fParent,view);
} else if(t instanceof Object){
$this.objBind(t,fParent,view,i);
}
})
}
});
})(jQuery);
</script>
<script>
let s=$("#app").bind({
a:"我的",
list:[{id:1,text:"请选择"},{id:2,text: "湖南"},{id:3,text: "上海"}],
},function (a,b){
console.log('触发',a)
let select= $('<select></select>')
$(b).empty().append(select[0]);
select.select2({
width:'100%',
data: a.list
})
})
s.list.push({id:4,text:"江苏"})
s.a="你的"
s.list[0].text="--选择--"
</script>
</body>
</html>