date1118封装数据劫持+渲染页面函数(全部完整代码)

86 阅读1分钟

一、封装数据劫持+渲染页面

基本思想:将一个普通的数据劫持的代码封装为函数,并将原始对象里的键值对写入到页面,而我使用的方法是使用到了实际项目中,也就是框架中的模式去封装的。

下面代码以及每一句的注释都在代码里面了。执行结果可以自己将代码复制到自己的运行其运行。

基本代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <-- html标签部分 -->
    <div id="app">
        <h1> {{name}} </h1>
        <h1> {{age}} </h1>
        <h1> {{sex}} </h1>
    </div>
    <script>
        /*
            数据验证与数据劫持部分
                1.验证标签以及传入的实参是否不为空
                2.对数据进行劫持的代码
        */
        // 数据验证
        // 封装一个验证数据的函数
        function Observer(options){
            
            // 数据验证部分
            // 如果root属性为空 就创建一个错误抛出
            if(options.root === undefined) throw new Error('您没有传递root属性,请重新传递');
            // 如果data数据为空 就创建一个错误抛出
            if(options.data === undefined) throw new Error('您没有传递data属性,请重新传递');
            // 如果div标签(#app)为空 就创建一个错误抛出
            const rootHTML = document.querySelector(options.root);
            if(rootHTML == null) throw new Error('您没有正确传递root属性,请重新传递');
            // 如果data属性传入的值不是一个对象 就创建一个错误抛出
            if(options.root == Object) throw new Error('您传入的data属性的属性值不是一个对象,请重新传递');
            
            // 数据劫持部分
            // 创建一个空对象 用来存储劫持后的数据
            const _data = {};
            // 存储一份原始数据内容
            let newDataStr = rootHTML.innerHTML;
            // 循环遍历原始数组里面的所有data值
            for(let k in options.data){
                // 数据劫持
                // 第一个参数: _data是劫持数据语法中的第一个属性 第一个属性写存储劫持数据的空对象_data
                // 第二个参数:k是循环遍历实参中的所有数据 也就是劫持的数据
                // 第三个参数:是劫持的的代码体
                Object defineProperty(_data , k , {
                    // 获取options中的键名
                    get(){
                        return options.data[k];
                    },
                    // 修改或者设置里面的数据 也就是劫持后的
                    set(val){
                        options.data[k] = val;
                    },
                })
            }
            // 最后返回劫持后的对象
            return _data;
        }
        
        
        // 渲染页面
        function rander(root , _data , newDataStr){
            // 先定义一个正则 用来获取里面的字符串内容
            let reg = /{{*\w+*}}/g;
            // 获取里面的所有字符串内容 并以数组的形式存储
            const res = rootHtmlStr.match(reg);
            // 通过循环遍历截获到的数组 
            res.forEach(item => {
                // console.log(item);
                // 拿到花括号的文本 因为这是对象中的key
                const key = reg.exec(rootHtmlStr)[1];
                // console.log(key);

                // 将原本花括号与内部文本 全部替换为对象中实际的值
                rootHtmlStr = rootHtmlStr.replace(/{{*(\w+)*}}/, _data[key]);
                console.log(rootHtmlStr);
            });

            // 重新将修改完毕的字符串 渲染到页面
            root.innerHTML = rootHtmlStr;
            
        }
    </script>
    
    
    <script>
        /*
              调用函数 并传入实参
        */
        let o1 = new Observer(
                  root:"#app",
                  data:{
                      name:'张三',
                      age:18,
                      sex:'男',
                  }
              )
              console.log(o1);
    </script>
</body>
</html>