• 支持IE6、IE7、IE8等低端浏览器的简化版vue


    最近研究Vue的底层原理,写了一个简化版的Vue,可以在支持IE6、IE7、IE8等低端浏览器运行。由于低端浏览器不支持对象属性定义,所以设置属性不支持直接赋值,需要调用虚拟机实例的set方法。目前只实现了基础的方法,后续继续完善!

    index.html

    <!DOCTYPE html>
    <html>
        <head>
            <title>简化版Vue</title>
            <script>
                window.onerror=function(){
                    return true;
                }
            </script>
        </head>
        <body>
            <hr />
            <div id="simpleVue">
                <button v-on:click="copy">戳我</button>
                <div>
                    <textarea v-model="name"></textarea>
                    <div v-text="name"></div>
                </div>
                <div>
                    <select v-model="name">
                        <option value="name1" selected>name1</option>
                        <option value="name2">name2</option>
                        <option value="name3">name3</option>
                    </select>
                </div>
                <hr>
                <button v-on:click="show">显示/隐藏</button>
                <div v-if="isShow">
                    <input type="text" style=" 300px" v-model="webSite">
                    <div v-text="webSite"></div>
                </div>
            </div>
            <script src="vmm.js"></script>
            <script>
            var vm = new VMM({
                el: '#simpleVue',
                data: {
                    name: '测试',
                    webSite: 'https://github.com/steezer',
                    isShow: true
                },
                methods: {
                    copy: function(){
                        vm.set('name', this.name +'测试');
                    },
                    show: function(){
                        vm.set('isShow', !this.isShow);
                    }
                }
            });
            </script>
        </body>
    
    </html>

    vmm.js

    function VMM(options){
        /**
         * 订阅器构造 用来接收属性值的相关数据的变化通知 从而更新视图
         * 
         * @param {Object} vm 虚拟机对象
         * @param {HTMLElement} el Node节点
         * @param {String} attr 属性名称
         * @param {Object} val 属性值
         */
        function Watcher(vm, el, attr, val){
            this.vm = vm;
            this.el = el;
            this.attr = attr;
            this.val = val;
            /**
             * 将收到的新的数据更新在视图中
             */
            this.update = function() {
                if (this.vm.$data[this.val] === true) {
                    this.el.style.display = 'block';
                } else if (this.vm.$data[this.val] === false) {
                    this.el.style.display = 'none';
                } else {
                    this.el[this.attr] = this.vm.$data[this.val];
                }
            }
            
            // 初始化订阅器时更新一下视图
            this.update();
        }
    
        /**
         * 获取对象
         * 
         * @param {Object|String} id 
         * @returns Object
         */
        function getElem(id){
            if(typeof(id)=='object'){
                return id;
            }
            var target=id+'',
                prefix=target.substr(0,1),
                target=target.substr(1);
            if(prefix=='#'){
                return document.getElementById(target);
            }
            if(prefix=='.'){
                return document.getElementsByClassName(target);
            }
            return document.getElementsByTagName(target);
        }
        
        function getAttr(elem, name) {
            var node = elem.getAttributeNode(name);
            if (node && node.specified) {
                return node.nodeValue;
            } else {
                return undefined;
            }
        }
        
        function addEvent(node, type, handle){
            if(document.addEventListener){
                node.addEventListener(type, handle, false);
            }else{
                node.attachEvent('on'+type, function(){
                    handle.call(node, arguments);
                });
            };
        }
        
        this.$el = getElem(options.el);
        this.$data = options.data;
        this.$methods = options.methods;
        this.oWatcherObj = {};
        
        // 获取属性
        this.get=function(key){
            return this.$data[key];
        }
        
        // 设置属性
        this.set=function(key, newVal){
            var value=this.$data[key];
            if (newVal !== value) {
                this.$data[key] = newVal;
                if(typeof(this.oWatcherObj[key])!="undefined"){
                    var watchers=this.oWatcherObj[key];
                    for(var i=0; i< watchers.length; i++){
                        watchers[i].update();
                    }
                }
            }
        }
        
        /**
         * 节点DOM解析器
         */
        this.compile=function(el) {
            var nodes = el.children,
                $this=this,
                addWatcher=function(node, attr, val){
                    if(typeof($this.oWatcherObj[val])=='undefined'){
                        $this.oWatcherObj[val]=[];
                    }
                    $this.oWatcherObj[val].push(new Watcher($this, node, attr, val));
                };
            // 迭代同级所有节点
            var values=[];
            for(var k in el){
                values.push(k)
            }
            
            for (var i = 0; i < nodes.length; i++) {
                var node = nodes[i],val;
                if (node.children.length > 0) {
                    this.compile(node); // 递归所有子节点
                }
                
                 // 点击事件
                val=getAttr(node, 'v-on:click');
                if (val) {
                    if(typeof($this.$methods[val])=="function"){
                        addEvent(node, 'click', (function(val){
                            return function(e){
                                $this.$methods[val].call($this.$data, e);
                            }
                        })(val));
                    }
                }
                
                // IF指令
                val=getAttr(node, 'v-if');
                if (val) {
                    addWatcher(node, "", val);
                }
                
                // Model
                val=getAttr(node, 'v-model');
                if (val) {
                    var event=node.tagName.match(/select/i) ? 'change' : 
                            ('oninput' in node ? 'input' : 'propertychange');
                    addWatcher(node, "value", val);
                    addEvent(node, event, (function(i, val){
                        return function(e){
                            $this.set(val, nodes[i].value);
                        }
                    })(i, val));
                }
                
                // Text
                val=getAttr(node, 'v-text');
                if (val) {
                    addWatcher(node, "innerText", val);
                }
                
                // Html
                val=getAttr(node, 'v-html');
                if (val) {
                    addWatcher(node, "innerHTML", val);
                }
            }
        }
        
        // 节点解析
        this.compile(this.$el);
    }
  • 相关阅读:
    Web安全实践
    认证授权的设计与实现
    Elasticsearch 分页查询
    【算法】三色旗
    【转】互联网项目中mysql应该选什么事务隔离级别
    Elasticsearch 聚合
    Elasticsearch 结构化搜索、keyword、Term查询
    Elasticsearch 单字符串多字段查询
    Elasticsearch 复合查询——多字符串多字段查询
    JavaScript 原型与原型链
  • 原文地址:https://www.cnblogs.com/springwind2006/p/12441991.html
Copyright © 2020-2023  润新知