美文网首页
Vue基础教程之-核心概念(二)

Vue基础教程之-核心概念(二)

作者: AC编程 | 来源:发表于2021-05-25 17:25 被阅读0次

    一、Vue注入

    1.1 注入概念

    配置对象中的部分内容会被提取到Vue实例中:data、methods,该过程称之为注入。

    如下代码

    <!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>
        <div id ="app">
            <!-- 界面模板 -->
            <!-- mustache -->
            <h1>系统名称:{{title}}</h1>
            <ul>
                <!-- v-for 指令-->
                <li v-for="(item,i) in products">
                    名称:{{item.name}} 
                    <button @click="changeStock(item,item.stock-1)">-</button>
                    <span v-if="item.stock>0">{{item.stock}}</span>
                    <span v-else>无货</span>
                    <button @click="changeStock(item,item.stock+1)">+</button>
    
                    <button @click="remove(i)">删除</button>
                </li>
            </ul>
        </div>
        <script src="./vue.min.js" ></script>
        <script>
            // vm:Vue实例
            var vm = new Vue({       //配置对象
                el:"#app",  // css选择器
                data:{      //和界面相关的数据
                    title:"库存管理系统",
                    products:[
                        {name:"iphone",stock:10},
                        {name:"xiaomi",stock:5},
                        {name:"huawei",stock:6},
                    ],
                },
                methods:{
                    remove(i){
                        this.products.splice(i,1);
                    },
                    changeStock(product,newStock){
                        if(newStock<0){
                            newStock = 0;
                        }
                        product.stock = newStock;
                    }
                },
            });
        </script>
    </body>
    </html>
    
    注入
    1.2 注入目的

    注入目的有两个

    • 完成数据响应式
    • 绑定this
    1.3 数据响应式vue是怎么知道数据被更改了?

    vue2.0是通过Object.defineProperty方法完成了数据响应式(更改数据后会调用该方法),这个是ES5的方式。
    vue3.0是通过Class Proxy完成的数据响应式。

    Class ProxyObject.defineProperty效率更高,Object.defineProperty有天生的缺陷,新增或删除了属性,Object.defineProperty无法感知

    1.3.1 新增属性无感知,界面不会重新渲染

    添加一个<p>{{abc}}</p>标签,abc这个属性暂时不存在,页面会报错,我们动态添加abc属性,并赋值为123,但页面没有显示出123的p标签,因此新增属性无感知,界面不会重新渲染。

    添加p标签 新增属性无感知,界面不会重新渲染
    1.3.2 删除属性无感知,界面不会重新渲染

    我们动态删除第一项的产品,delete vm.products[0],界面没有重新渲染。

    删除属性无感知,界面不会重新渲染
    1.4 注入目的绑定this
    // vm:Vue实例
            var vm = new Vue({       //配置对象
                el:"#app",  // css选择器
                data:{      //和界面相关的数据
                    title:"库存管理系统",
                    products:[
                        {name:"iphone",stock:10},
                        {name:"xiaomi",stock:5},
                        {name:"huawei",stock:6},
                    ],
                },
                methods:{
                    remove(i){
                        this.products.splice(i,1);
                    },
                },
            });
    

    remove方法中的this,按道理来说,应该指向的是methods,但现在指向的是vm实例。原因是methods.remove先提取到Vue实例中了,并绑定了thisvm,类似于 methods.remove.bind(vm)

    二、虚拟DOM树

    2.1 虚拟DOM树概览

    为了提高渲染效率,Vue会把模板编译为虚拟DOM树,然后再生成真实的DOM

    模板-虚拟DOM-真实DOM

    console.dir(document.body) 可以打印出真实DOM树结构

    真实DOM树

    vm._vnode 可查看虚拟DOM

    虚拟DOM树

    当数据更改时,将重新编译成虚拟DOM树,然后对前后两棵树进行对比,仅将差异部分反映到真实DOM,这样即可最小程度的改动真实DOM,提升页面效率。

    diff算法
    2.2 提升Vue效率

    因此,对于vue而言,提升效率重点着眼于两个方面:

    • 减少新的虚拟DOM的生成
    • 保证对比之后,只有必要的节点有变化
    2.3 Vue生成虚拟DOM树的方式

    Vue提供了多种方式生成虚拟DOM树
    1、在挂载的元素内部直接书写,此时将使用元素的outerHTML作为模板

    outerHTML

    2、在template配置中书写

    在配置里加template

    <!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>
        <div id ="app">
        </div>
        <script src="./vue.min.js" ></script>
        <script>
            // vm:Vue实例
            var vm = new Vue({       //配置对象
                el:"#app",  // css选择器
                template:`
                <div id ="app">
                    <!-- 界面模板 -->
                    <!-- mustache -->
                    <h1>系统名称:{{title}}</h1>
                    <ul>
                        <!-- v-for 指令-->
                        <li v-for="(item,i) in products">
                            名称:{{item.name}} 
                            <button @click="changeStock(item,item.stock-1)">-</button>
                            <span v-if="item.stock>0">{{item.stock}}</span>
                            <span v-else>无货</span>
                            <button @click="changeStock(item,item.stock+1)">+</button>
    
                            <button @click="remove(i)">删除</button>
                        </li>
                    </ul>
                </div>
                `,
                data:{      //和界面相关的数据
                    title:"库存管理系统",
                    products:[
                        {name:"iphone",stock:10},
                        {name:"xiaomi",stock:5},
                        {name:"huawei",stock:6},
                    ],
                },
                methods:{
                    remove(i){
                        this.products.splice(i,1);
                    },
                    changeStock(product,newStock){
                        if(newStock<0){
                            newStock = 0;
                        }
                        product.stock = newStock;
                    }
                },
            });
        </script>
    </body>
    </html>
    

    3、在render配置中用函数直接创建虚拟节点树,此时,完全脱离模板,将省略编译步骤

    render方法

    <!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>
        <div id ="app">
        </div>
        <script src="./vue.min.js" ></script>
        <script>
            // vm:Vue实例
            var vm = new Vue({       //配置对象
                el:"#app",  // css选择器
    
                render(h){
                    return h("div",[
                        h("h1",this.title),
                        h("p","首页")
                    ]);
                },
            
                data:{      //和界面相关的数据
                    title:"库存管理系统",
                },
            });
        </script>
    </body>
    </html>
    
    render方式

    我们可以用这种方式动态生成6级标题

    <!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>
        <div id ="app">
        </div>
        <script src="./vue.min.js" ></script>
        <script>
            // vm:Vue实例
            var vm = new Vue({       //配置对象
                el:"#app",  // css选择器
    
                render(h){
    
                    var titles = [];
    
                    for(var i = 1;i<=6;i++){
                        titles.push(h(`h${i}`,`${i}级标题`));
                    }
    
                    return h("div",titles);
                },
            
                data:{      //和界面相关的数据
                    title:"库存管理系统",
                },
            });
        </script>
    </body>
    </html>
    
    动态生成6级标题

    这些步骤从上到下,优先级逐渐提升

    注意:虚拟节点树必须是单根的
    原因是diff算法只能对比前后两棵树,如果是多根节点,则会生成多棵树,diff算法无法对比。

    三、挂载

    将生成的真实DOM树,放置到某个元素位置,称之为挂载。挂载的方式:
    1、通过el:"css选择器" 进行配置
    2、通过vue实例.$mount("css选择器") 进行配置

    四、完整流程

    完整流程

    源码

    源码 001

    相关文章

      网友评论

          本文标题:Vue基础教程之-核心概念(二)

          本文链接:https://www.haomeiwen.com/subject/kqtcsltx.html