js简单实现Vue2动态渲染

作为一名后端,一直想不通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>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值