VUE

1、基础篇

1.1、初识Vue

准备
VsCode 插件 VeturPrettier-Code formatter

浏览器工具 vuejs devtool

vue基础

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>01-初识vue.html</title>

    <!-- 0、导入vue.js -->
    <script src="../js/vue.js"></script>
</head>
<body>

    <!-- 1、定义一个容器 -->
    <div id="app">

        <h3> 第一个vue程序,并使用插值表达式取得值为:{{name}} </h3>
    </div>

</body>

<script>

    // 去除浏览器控制台中的错误信息  可以尝试去掉这个,然后进入浏览器控制台,观察上面报的东西
    Vue.config.productionTip = false;

    // 2、初始化Vue容器
    new Vue({
        el: "#app",
        data: {
            name: "紫邪情",
            age: "18"
        }
    })
</script>

</html>

  • Vue容器中的代码一样符合html规范,只不过是混入了一些Vue的特殊用法而已,这个容器中的代码被称为:Vue模板
  • {{xxx}}中的xxx要写js表达式( {{}} 即为插值表达式 ),且xxx可以自动读取到data中的所有属性
  • 一旦data中的数据发生改变,那么页面中使用该数据的地方一样发生改变

1.2、认识v-bind - 数据单向绑定


 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>02-vue之v-bind</title>
 
     <script src="../js/vue.js"></script>
 </head>
 <body>
 
     <div id="app">
         <!-- 常规写法:v-bind绑定的是属性 -->
         <a v-bind:href="url"></a> 
             <!-- 多层嵌套取值:插值表达式   取的东西就是下面Vue实例new Vue({})
                 data中的东西,可以理解为在找寻集合中的元素
             -->
         <h3>{{person.name}}</h3>
         <!-- 简写 -->
         <h3 :mySex="person.sex">{{person.name}}</h3>        
     </div>
     
 </body>
 
 <script>
 
     Vue.config.productionTip = false;
 
     new Vue({
         el: "#app",     // el指定的是为哪一个容器服务  值就是一个css中的选择器
         data: {         // data存储的就是数据,这些数据是供el指定的容器去用的
             url: "https://www.cnblogs.com/xiegongzi/",
 
             person: {
                 name: "紫邪情",
                 sex: "女"
             }
         }
     })
 </script>
 </html>
 

小结:Vue模板有两大类

  • 1、插值语法,前面已经见到了,就是:{{ 取data中保存的数据 }}
    • 功能:解析标签体的内容
    • 注意:{{}}中的东西必须是js表达式
  • 2、指令语法
    • 功能:解析标签( 包括属性、标签体内容、绑定事件… )
    • 例子: v-bind:herf = “xxxx” 或简写为 :herf = “xxxx” 注意:xxx同样要写成js表达式
    • 另外:Vue中有很多指令语法,形式都是: v-xxxx 如:v-bind、v-model、v-if、v-for、v-on…,而且一些指令也都可以简写

1.3、认识Vue的数据绑定

这里需要了解mvvm模式,要理解,可以参照java中的mvc模式

 
 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>03-v-model</title>
 
     <script src="../js/vue.js"></script>
 </head>
 <body>
 
     <div id="app">
         <!-- 单向绑定:绑的是属性 -->
         单向绑定:<input type="text" :value="name">  <br/>
         <!-- 双向绑定:绑的是值 -->
         双向绑定:<input type="text" :myName="name" v-model:value="username">   <br/>
         <!-- 双向绑定的简写 因为:model绑的就是值,因此:value可以省掉 -->
         双向绑定:<input type="text" :myName="name" v-model="username">
     </div>
     
 </body>
 
 <script>
 
     Vue.config.productionTip = false;
 
     new Vue({
         el: "#app",
         data: {
             name: "紫邪情",
             username: "邪公子"
 
         }
     })
 </script>
 </html>

数据绑定小结:Vue中数据绑定有两种方式

  • 1、单向绑定( v-bind ),数据只能从data流向页面
  • 2、双向绑定 ( v-model ) ,数据不仅能从data流向页面,还可以从页面流向data,但需注意如下两点
    • 双向绑定一般都应用在表单类元素上( 如:input、select等 )
    • v-model:value 可以简写为 v-model,因为:v-model默认收集的就是值

1.4、el和data的两种写法


 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>04-vue的el和data的两种写法</title>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app"></div>
 
     <script>
       // 创建 vm 实例对象
       const vm = new Vue({
         //指定控制的区域
         // el:'#app',   // el 常规写法
         // data:{},     // data 常规写法 ———— 这种也叫对象式写法
 
         // data 函数式写法,这种写法后续经常见
         data () {   // 这里使用data:function(){}也可以,但是:绝对不能写成data:()=>{}
                     // 因为这种写法变质了,成为Window对象了,这样后续用this指向时,这个this所指代的就不Vue实例了
           return {
             
           }
         }
        });
 
        // el 另外的写法
        vm.this.$mount('#app')     // 这种写法需要记住,后续组件化开发需要用到
     </script>
   </body>
 </html>

小结:el和data的两种写法

  • 1、el
    • (1)、new Vue时配置el选项
    • (2)、先创建Vue实例,然后再通过vm.this.$mount( ‘#app’ ) 来指定el的值
  • 2、data
    • (1)、对象式
    • (2)、函数式
    • 如何选择哪种用法:目前都可以,但是后续会玩组件,则:必须用函数式,而且不可以用兰姆达表达式( 即:上面的data:()=>{},否则:会出错 )
  • 3、一个原则:
    • 由Vue管理的函数,一定不要写箭头函数,就上面的兰姆达表达式,否则就会导致this不再是Vue实例了( 这个this有大用处,在"new Vue中"用了this就是指的当前的Vue实例,后续可以通过这个this玩很多东西 )

1.5、理解MVVM模型

  • M 指:model
  • V 指:view
  • VM 指:viewmodel


 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>理解MVVM</title>
 
     <script src="../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>姓名:{{name}}</h2> <br>
         <h2>性别:{{sex}}</h2>   
         <hr>
         <h2>智商:{{1+1}}</h2>
     </div>
 
     <script>
       // 创建 vm 实例对象
       const vm = new Vue({
         //指定控制的区域
         el:'#app',
         data:{
             name: "紫邪情",
             sex: "女"
         },
        });
 
        console.log( vm );
     </script>
   </body>
 </html>
 

小结:MVVM模型

  • 1、M:Model( 模型 ) ————> data中的数据
  • 2、V:View( 视图 ) —————> 模板代码
  • 3、ViewModel:视图模型( ViewModel ) ————> Vue实例

1.6、回顾Object.defineProperty()函数

<!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>05-了解object.defineProperty()</title>
     <script src="../js/vue.js"></script>
   </head>
 
   <body>
     <script>
 
       Vue.config.productionTip=false;
       
       let sex = '女'
       let person = {
         name: '紫邪情'
       }
 
       //  参数说明:person 为要修改的对象  sex为具体修改的对象中的哪个属性  {} 对修改属性的配置
        Object.defineProperty( person , 'sex' , {
         //  以下就是{}中的相关配置
         //  value: '男',
         //  enumerable: true,    // 这个sex是否可以被遍历
         //  writable: true,      // 这个sex是否可以被修改
         //  configurable: true,   // 这个sex是否可以被删除
 
          // 当有人获取sex这个属性时会触发这个get()方法
          get(){
             console.log('有人读取sex属性了');
             return sex;
           },
 
           // 当有人修改sex属性的值时会触发这个set方法
           set(value){
             console.log('有人修改了sex的值');
             return sex = value;
           }
         
        });
 
     </script>
   </body>
 </html>
  • 注意:去找temp或者值是调用了get()方法进行获取的,相应的set()方法也知道是怎么回事了

1.7、简单理解数据代理原理

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>06-简单理解数据代理</title>
   </head>
 
   <body>
 
     <script>
 
         let obj1 = {x:100};
         let obj2 = {y:200};
 
         // 数据代理: 通过一个对象代理 对 另一个对象中属性的操作( 读 / 写 )
         Object.defineProperty(obj2 , 'x' , {
           get(){
             console.log("有人获取了x的值");
             return obj1.x;
           },
 
           set(value){
             console.log("有人修改了x的值");
             obj1.x = value;
           }
         })
     </script>
   </body>
 </html>

小结:Vue中的数据代理

  • 1 、通过vm对象来代理data对象中的属性的操作( 读 / 写 )
  • 2、好处:更加方便操作data中的数据
  • 3、原理:
    • 通过object.defineProperty()把data对象中所有属性添加到vm上
    • 为每一个添加到vm上的属性,都指定一个 getter / setter
    • 在getter / setter内部去操作( 读 / 写 )data中的属性

1.8、事件绑定及其修饰符

 
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>07-事件绑定及其修饰符</title>
 
     <script src="../js/vue.js"></script>
   </head>
 
   <!-- 
         常用的事件修饰: 事件、事件,放在对应事件后就可以了,如:@click.prevent = "xxxx"
             prevent     表示:阻止默认事件的触发
             stop        表示:阻止事件冒泡
             once        表示:只执行一次事件
 
    -->
   
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
 
         <!-- vue中事件绑定的简单写法 -->
         <button v-on:click="showInfo()">点我显示提示信息</button>
 
         <br/>
 
         <!-- vue中事件绑定的简写 还可以传递参数 -->
         <button @click="showInfo2($event, 66)">点我获取带参的事件信息</button>
     </div>
 
     <script>
 
         Vue.config.productionTip=false;
         
       // 创建 vm 实例对象
       const vm = new Vue({
         //指定控制的区域
         el:'#app',
         data:{},
 
         methods: {
             showInfo(){
                 alert("这是vue中的事件绑定");
             },
 
             showInfo2(event , number){
                 console.log(event + "=====>" + number);
             }
         }
        });
     </script>
   </body>
 </html>

小结 事件的使用

  • 1、使用v-on:xxxx,或 @xxx 来绑定事件,xxxx就是事件名
  • 2、事件的回调需要配置在methods对象中,最终会在vm上
  • 3、methods中配置的函数,记得不要用兰姆达函数啊( 前面说过的 ),否则this无效了
  • 4、methods中配置的函数,都是被Vue所管理的函数,this指向的就是vm 或 组件实例对象
  • 5、@click = “demo” 和 @click = “demo( $event )效果一致,但是:后者可以传参( 后续有用 )

1.9、计算属性

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>10-计算属性conputed</title>
 
     <script src="../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         姓名: <input type="text" v-model="name"> <br/>
         性别: <input type="text" v-model="sex">
         <hr>
         信息: <span>{{info}}</span>
     </div>
 
     <script>
 
     Vue.config.productionTip=false;
       // 创建 vm 实例对象
       const vm = new Vue({
         //指定控制的区域
         el:'#app',
         data:{
             name:'紫邪情',
             sex:'女'
         },
 
         // 所谓的计算属性:就是通过已有属性( 一般为data中的 )计算得来
         computed: {
             info:{
                 get(){
                     console.log('开始调用get()');
                     return this.name + '-' + this.sex
                 },
 
                 set(value){
                     console.log('开始调用set()' + value);
                     
                     // 计算属性要被修改,那必须写set()去响应修改,且set()中要引起计算时依赖的数据发生改变
                     const arr = value.split('-');
                     this.name = arr[0];
                     this.set = arr[1];
                 }
             }
         }
        });
     </script>
   </body>
 </html>

计算属性小结

  • 1、定义:要用的属性不存在,要通过已有属性计算得来

  • 2、原理:借助了object.defineproperty()的getter和setter

  • 3、get()什么时候执行

    • 1、初次读取时会执行一次
    • 2、当依赖的数据发生改变时会再次被调用
  • 4、优势:与methods相比,内部有缓存机制( 复用 ),效率更高、调试方便

  • 5、注意:

    • 1、计算属性最终都会在vm( Vue实例 )上,直接读取即可
    • 2、若计算属性要被修改,那必须写set()去响应修改,且set()中要引起计算时依赖的数据发生改变( 例子中没有做这一步 )
  • 6、计算属性是可以简写的
    就是把set()去掉,因为:更多时候是读取,并不修改,同时修改还要去控制台( 刷新就又没了 ),因此:把set()去掉就是计算属性的简写

1.9.1、结合computed、methods、v-on做一个小Demo

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>11 - 使用计算属性做一个Demo</title>
 
     <script src="../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>你是:{{result}}</h2>
 
         <button @click="changeResult">切换名字</button>
     </div>
 
     <script>
        // 去除浏览器控制台中的错误信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         //指定控制的区域
         el:'#app',
         data:{
             name: true
         },
 
         computed:{
             result(){
                 return this.name?'紫邪情':'紫女'
             }
         },
 
         methods: {
             changeResult(){
                 return this.name = !this.name
             }
         },
        });
     </script>
   </body>
 </html>
 

我们主要做的是图中的这一步,因此:简化 ———— 衍生出v-on的另外一个玩法


 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>12 - 使用计算属性做一个Demo 简化</title>
 
     <script src="../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>你是:{{result}}</h2>
 
         <!-- @xxx = 'yyyy' 如果只是做一件简单的事情,那么就可以使用下面的方式
               因为:v-on是可以支持js表达式的( 注意:不是js代码啊 )
               但是:如果这个v-on需要做多件事,那么最好就别这么玩
                     如:切换了名字,还要弄一个弹窗( 切换成功 )这种就别玩
         -->
         <button @click="name = !name">切换名字</button>
     </div>
 
     <script>
        // 去除浏览器控制台中的错误信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         //指定控制的区域
         el:'#app',
         data:{
             name: true
         },
 
         computed:{
             result(){
                 return this.name?'紫邪情':'紫女'
             }
         },
 
         // methods: {
         //     changeResult(){
         //         return this.name = !this.name
         //     }
         // },
        });
     </script>
   </body>
 </html>
 

1.10、监视属性

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>13 - 监视属性 watch</title>
 
     <script src="../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>你是:{{result}}</h2>
 
         <button @click= "name = !name">切换名字</button>
     </div>
 
     <script>
        // 去除浏览器控制台中的错误信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         //指定控制的区域
         el:'#app',
         data:{
             name: true
         },
 
         computed: {
             result() {
                 return this.name?'紫邪情':'紫女'
             }
         },
 
         // 监视属性 watch  监视的是属性,也就是data中和computed中的都可以监视
         // 现在这种我是用的简写形式 ———— 前提是:只需要使用handler()中的东西时,handler后续会用完整形式
         watch: {
             name( newValue, oldVaule ){ // 表示的是:监视哪个属性
                 console.log('属性发生变化了' , newValue , oldVaule);
             }
         },
        });
 
     //    当然:监视属性还有一种写法,就是利用Vue的内置函数
 /*     vm.$watch( 'name', {  // 这里的name就是指监听哪个属性  而且必须是' '引起来的
         handler( newValue, oldVaule ){
             console.log('属性发生变化了' , newValue , oldVaule);
         }
      }) */
     </script>
   </body>
 </html>
 

监视属性 watch小结

  • 1、当被监视的属性变化时,回调函数自动调用,进行相关操作
    回调函数:指的是:handler() ,第一种写法也是可以用handler,只是把watch换成了$watch而已,后面步骤其实是一样的,只是我把第一种给简写了而已

  • 2、监视的属性必须存在,才能进行监视

  • 3、监视有两种写法

    • (1)、new Vue时传入watch配置
    • (2)、通过vm.$watch内置函数进行监视
1.10.1、深度监视 - 需要掌握的一种


<!DOCTYPE html>
<html lang="en">
 <head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>14 - 深度监视</title>

   <script src="../js/vue.js"></script>
 </head>

 <body>
   <!-- 被 vm 实例所控制的区域 -->
   <div id="app">
       <h2>你是:{{result}}</h2>

       <!-- 现在这个name就是person里面的了,这就是需要监视多层属性变化 -->
       <button @click= "person.name = !person.name">切换名字</button>
   </div>

   <script>
      // 去除浏览器控制台中的错误信息
     Vue.config.productionTip = false;

     // 创建 vm 实例对象
     const vm = new Vue({
       //指定控制的区域
       el:'#app',
       data:{
           person:{
               name: true
           }
       },

       computed: {
           result(){
               return this.person.name?'紫邪情':'紫女'
           }
       },

       // 下面这种事监视属性的完整写法,前面玩的一个是简写形式
       watch: {
           person:{
               // 监视多层结构中所有属性的变化
               deep: true,     // 深度监视 就做了这一步操作而已
           /* 
               Vue中watch默认是不可以监视属性更里层的,
               如:上面person只可以监视person本身这个属性,理解的话,
               可以采用对象空间值来比对,假如:person空间地址是是01x23,
               那么Vue只会监视这个空间变量有没有发生改变,而内层就不可以监视,
               因为:内层中的属性改变了,但是person这个对象本身并没有改变
            */
                handler(){
                   console.log('属性改变了');
               } 
           }
       }
      });
   </script>
 </body>
</html>



深度监视小结

  • 1、Vue中的watch默认不监视对象内部值得改变( 监视的是一层 )
  • 2、配置deep:true可以监视对象内部值得改变( 监视多层 )
  • 注意:
    • 1、Vue自身可以监视对象内部值得改变,但Vue提供的watch默认不可以
      这个可以验证的,使用多层属性,最后是绑定在vm上的,那么在控制台使用vm去改变值,那么页面再去观察页面就可以发现效果了,这里是为了解释Vue不是不可以监视多层的改变,只是:watch默认不支持
    • 2、使用watch时根据数据的具体结构( 属性是一层还是多层嘛 ),决定是否采用深度监视

1.11、computed和watch的坑


 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>15 - computed和watch的坑</title>
 
     <script src="../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         姓: <input type="text" v-model="firstname"> <br/>
         名: <input type="text" v-model="lastname">
 
         <hr/>
 
         信息: {{fullname}}
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         //指定控制的区域
         el:'#app',
         data:{
             firstname: '紫',
             lastname: '邪情',
             fullname: '紫邪情'
         },
 
         watch: {
             firstname(val){
                 this.fullname = val + this.lastname;
             },
 
             lastname(val){
                 this.fullname = this.firstname + val;
             }
         }
        });
     </script>
   </body>
 </html>

用computed实现


     <!DOCTYPE html>
     <html lang="en">
       <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, initial-scale=1.0">
         <meta http-equiv="X-UA-Compatible" content="ie=edge">
         <title>02 - computed实现</title>
 
         <script src="../../js/vue.js"></script>
       </head>
 
       <body>
         <!-- 被 vm 实例所控制的区域 -->
         <div id="app">
             姓: <input type="text" v-model = "firstname">   <br/>
             名: <input type="text" v-model = "lastname">
 
             <hr/>
 
             信息: {{fullname}}
         </div>
 
         <script>
            // 去除浏览器控制台中的警告提示信息
           Vue.config.productionTip = false;
 
           // 创建 vm 实例对象
           const vm = new Vue({
             //指定控制的区域
             el:'#app',
             data:{
                 firstname: '紫',
                 lastname: '邪情'
             },
 
             computed: {
                 fullname(){
                     return this.firstname + this.lastname;
                 }
             }
            });
         </script>
       </body>
     </html>
 

最后运行的效果都是一样的,但是:虽然看起来没区别,可是computed和watch还是有区别的,假如:现在我需要让姓改了之后,隔1s之后再显示到信息那里。那么:computed无法做到,但是watch就可以

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>03 - 用watch实现异步操作</title>
 
     <script src="../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         姓: <input type="text" v-model = "firstname"> <br/>
         名: <input type="text" v-model = "lastname">
 
         <hr/>
 
         信息: {{fullname}}
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             firstname: '紫',
             lastname: '邪情',
             fullname: '紫邪情'
         },
 
         watch: {
             firstname(val){
                 // 一定需要注意:这里必须使用兰姆达表达式() =>{}
                 /* 
                     前面说过,Vue所管理的函数,切记别用兰姆达表达式,智能用函数式
                             这是为了能够通过this拿到vm实例的东西而已
                     但是注意:这里这个setTimeout()定时函数是Vue所管理的吗?
                             不是,而后面需要的val是哪里的?是Vue实例中的,修改的值
                             是在Vue实例身上
                             所以:想要拿到Vue身上的val怎么弄?页面的展示都是js引擎帮忙去进行操作 / 找寻的
                             因此:利用js引擎做文章,让它找的时候自动去层级查找,它执行到里面的this.fullname = val + this.lastname时
                             会去找this是谁,()=>{}这里是用的兰姆达表达式,这就会指向Window对象,而Window上没有fullname,所以就会
                             往外找,找到firstname(val)这是函数式,指向的就是Vue实例,也就找到了fullname、val.....
                 */
                 setTimeout( () => {
                     this.fullname = val + this.lastname;
                 }, 1000);
             },
 
             lastname(val){
                 this.fullname = this.firstname + val;
             }
         }
        });
     </script>
   </body>
 </html>

而利用computed就不可以做到上面的这种异步操作
computed和watch的区别

  • 1、computed能完成的功能,watch绝对都可以做到
  • 2、watch能完成的功能,computed不一定可以做到,如:上面举的例子进行异步操作
  • 3、原则:
    • 1、凡是被Vue所管理的函数,最好都写成函数式( 即:普通函数 ),这是为了能够让this指向Vue实例 或 组件实例对象( 后续会见到 ),这样就可以通过this拿到它们对应的东西
    • 2、凡是不被Vue所管理的函数( 如:定时器里面的回调函数、ajax中的回调函数… ),最好都写成兰姆达表达式( 即:箭头函数 ),这样做也是为了能够让this指向Vue实例 或 组件实例对象

1.12 样式绑定

1.12.1、class样式绑定

class样式绑定小结

  • 1、字符串写法,适用于:class名字不确定时使用
  • 2、数组写法,适用于:class名字、个数都不确定时使用
  • 3、对象写法,适用于:class名字确定、但个数不确定( 如:例子中的login1可能用,可能不用,而login2也是一样,所以这就是各种组合 )
1.12.2、style行内样式绑定

class和style样式绑定小结

  • 1、class样式绑定

    • 写法 :class = “xxxx”,其中xxxx可以使字符串、数组、对象
    • 字符串写法适用于:类名不确定、要动态获取( 交由Vue管理,随时调试 )
    • 数组写法:要绑定多个样式、class名字和个数都不确定
    • 对象写法:要绑定多个样式、class名字确定而个数不确定( 个数不确定是因为不知道某个样式用不用 )
  • 2、style样式绑定

    • 写法 :style = “xxx",其中xxx可以是对象、数组
      对象写法是推荐用的一种
  • 3、原则

    • 在Vue中静态不变的东西,就放在Vue模板中即可( 即:那个div容器中 ),而动态改变的东西就放在Vue实例身上

1.13 条件渲染

1.13.1、v-if

注意:
v-if、v-else-if、v-else组合用时,需要留意代码是紧挨着的即可,这就好比:java的Mybatis框架的pageHelper分页插件,用startPage和pageInfo联合使用一样( 数据查询完了之后放到pageInfo<>()中,这二者中间就不可以夹杂另外的语句,否则报错 )

1.13.2、v-if配套工具template

注意事项:template“只能”与v-if搭配使用

1.13.3、v-show
  • 1、v-if会了,那么v-show就会了,用法和单纯的v-if一模一样
  • 2、不过它和v-if的原理不一样

v-if和v-show小结

  • 1、v-if

    • (1)、v-if = “表达式”
    • (2)、v-else-if = “表达式”
    • (3)、v-else = “表达式”
    • (4)、适用于:切换频率较低的场景,因为:v-if是直接把不展示的DOM元素给移除掉
    • (5)、特点:不展示的DOM直接移除
    • (6)、注意:v-if可以和v-else-if、v-else一起使用,但是:要求结构不可以被“打断”( 代码紧挨着 )
  • 2、v-show

    • (1)、v-show = “表达式”
    • (2)、适用于:切换频率较高的场景
    • (3)、特点:不展示的DOM元素未被移除,仅仅是使用display:none样式给隐藏掉了而已
  • 3、注意:使用v-if时,元素可能无法获取到,而使用v-show,则:一定可以获取到
    因为:v-show是做了样式修改,但是DOM节点还在,所以是可以操作这个DOM节点的,但是:v-if是直接把DOM元素给移除掉了( 万一是误操作而导致把v-if的值弄为false了,那后续万一其他地方用到了v-if移除的节点呢?不就裂开了吗 )

1.14 循环结构

1.14.1、v-for
 
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>1 - 认识v-for</title>
 
     <script src="../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <!-- 1、遍历数组 -->
         <h2>人员信息</h2>
         <!-- 简写形式 -->
         <ul>
             <li v-for = "p in persons" :key="p.id">
                 {{p.name}} ----- {{p.age}}
             </li>
             <!-- 
                 v-for就和js中的for in差不多
                 :key="p.id"  此处:是给每一个li节点绑定一个唯一的id( 和身份证号一样 就相当于是<li id = ‘xxx’> ),此时不写没事,但是最好都带上,后续有用
                 p  代表的就是:从persons中遍历出来的每一条数据
              -->
         </ul>
 
         <!-- 完整写法 -->
         <ul>
             <li v-for = "(val,index) in persons" :key="val.id">
                 {{val.name}} ----- {{val.age}} ------ {{index}}
             </li>
         </ul>
 
 
         <!-- 2、遍历对象 -->
         <h2>神奇之地</h2>
         <ul>
             <li v-for = "(val,index) in like" :key="index">
                 {{val}} ------ {{index}}
             </li>
         </ul>
 
         <!-- 其实另外还有:v-for还可以遍历字符串、某个数字( 循环这个数字这么多次 ),但是这两种基本上都不用,所以不说明了 -->
 
 
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             persons: [
                 // 数组中又放得有对象
                 {'id':'10001','name':'紫邪情','age':'18'},
                 {'id':'10002','name':'紫女','age':'18'},
                 {'id':'10003','name':'邪公子','age':'19'}
             ],
 
             like: {
                 name: '香牌坊',
                 ko:'范冰冰'
             }
         },
        });
     </script>
   </body>
 </html>

v-for小结

  • 1、语法:v-for = “ ( item,index ) in xxx ” :key = “yyy”
  • 2、可遍历:数组、对象、字符串( 用得少 )、指定次数( 用得更少 )
  • 3、可用于:展示列表数据
1.14.2、key值的坑( 作用与原理 )

在前面v-for中key值使用index时有一些坑的,正确的做法是:最好使用数据的id作为key值,但不是说index作为key值就是错的,前面演示过了,是正常效果,可是:在特定的场景下使用 :key = "index"就会出问题


 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>2 - key值的坑</title>
 
     <script src="../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>人员信息</h2>
         <ul>
             <!-- 这里使用index作为key值 -->
             <li v-for = " (p , index) in persons" :key="index">
                 {{p.name}} ----- {{p.age}} <input type="text">
             </li>
         </ul>
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             persons:[
                 {'id':'001' , 'name':'张三','age':'18'},
                 {'id':'002' , 'name':'李四','age':'19'},
                 {'id':'003' , 'name':'王五','age':'20'}
             ]
         },
        });
     </script>
   </body>
 </html>
 

小结

  • 1、虚拟DOM中key的作用
    key是虚拟DOM对象的标识,当状态中的数据发生改变时,Vue会根据【 新数据 】生成【 新的虚拟DOM 】
    随后Vue进行【 新虚拟DOM 】 与【 旧虚拟DOM 】的差异比较( 对比算法 / diff算法 )

  • 2、对比算法的规则

    • (1)、旧虚拟DOM中找到了与新虚拟DOM相同的key
      若虚拟DOM中内容没变,则:直接使用之前的真实DOM
      若虚拟DOM中内容变了,则:生成新的真实DOM,随后替换掉页面中之前的真实DOM
    • (2)、旧虚拟DOM中未找到与新虚拟DOM相同的key
      直接创建新的真实DOM,虽然渲染到页面
  • 3、用index作为key值可能会引发的问题

    • (1)、若对数据进行:逆序添加、逆序删除…等破坏数据顺序的操作
      则:会产生不必要的真实DOM更新 即:界面显示没问题,但:效率低( 效率低是因为:最后生成真实DOM时,文本节点是重新生成的 )
    • (2)、若结构中还包含输入类( 如:例子中的input )的DOM
      则:会产生错误DOM更新 即:页面中数据错位
  • 4、开发中如何选择key?

    • (1)、最好使用数据自己的唯一标识作为key值,比如:手机号、身份证号…( 直接利用数据库中的主键id也行 )
    • (2)、如果不存在对数据逆序添加、逆序删除等破坏数据顺序的操作,只用来渲染列表页面,则:使用index作为key是莫问题的
1.14.3、列表过滤

1、使用watch实现


 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>3 - 列表过滤( 查询功能 )</title>
 
     <script src="../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <H2>人员信息列表</H2>
 
         搜索:<input type="text" placeholder="请输入搜索词" v-model="keyWord">
         <ul>
             <li v-for = " p in filterPersons" :key="p.id">
                 {{p.name}} -------- {{p.age}}
             </li>
         </ul>
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             // 1、搜集搜索框中的内容 搜索框内容变,这里的内容也要变,所以:双向绑定v-model
             keyWord: '',
 
             // 2、准备初始数据
             persons: [
                 {'id':'10001','name':'紫邪情','age':'18'},
                 {'id':'10002','name':'紫邪晴','age':'19'},
                 {'id':'10003','name':'邪公子','age':'20'},
                 {'id':'10004','name':'公孙策','age':'21'},
                 {'id':'10005','name':'孙悟空','age':'22'}
             ],
 
             // 4、需要准备另一个容器来装过滤之后的数据
             filterPersons: []
         },
 
         // 3、使用watch来实现搜索效果
         /* 
             需要做两件事
                 (1)、拿到data的keyWord中的内容
                 (2)、使用keyWod中的内容 去 persons中进行过滤筛选,从而把结果渲染到页面
         */
        watch: {
            keyWord: {
                // 这个的作用:页面初始化时就执行一次handler()
                immediate: true,
 
                handler(newVal){
                    // 1)、过滤数据 把结果放到filterPersons中去
                    this.filterPersons = this.persons.filter( (p)=>{
                        // 没在数组中indexOf()返回的就是-1
                         return p.name.indexOf(newVal) !== -1
                     })
                }
            }
        }
        });
     </script>
   </body>
 </html>

2、使用computed实现


 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>3 - 列表过滤( 查询功能 )</title>
 
     <script src="../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <H2>人员信息列表</H2>
 
         搜索:<input type="text" placeholder="请输入搜索词" v-model="keyWord">
         <ul>
             <li v-for = " p in filterPersons" :key="p.id">
                 {{p.name}} -------- {{p.age}}
             </li>
         </ul>
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             // 1、搜集搜索框中的内容 搜索框内容变,这里的内容也要变,所以:双向绑定v-model
             keyWord: '',
 
             // 2、准备初始数据
             persons: [
                 {'id':'10001','name':'紫邪情','age':'18'},
                 {'id':'10002','name':'紫邪晴','age':'19'},
                 {'id':'10003','name':'邪公子','age':'20'},
                 {'id':'10004','name':'公孙策','age':'21'},
                 {'id':'10005','name':'孙悟空','age':'22'}
             ],
         },
 
         // 3、使用computed来实现搜索效果
         /* 
             需要做两件事
                 (1)、拿到data的keyWord中的内容
                 (2)、使用keyWod中的内容 去 persons中进行过滤筛选,从而把结果渲染到页面
         */
        computed: {
            filterPersons() {
                return this.persons.filter( (p)=>{
                    return p.name.indexOf( this.keyWord ) !== -1
                })
            }
        }
        });
     </script>
   </body>
 </html>
 
1.14.4、列表排序

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>4 - 列表排序</title>
 
     <script src="../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>人员信息</h2>
         搜索: <input type="text" v-model = "keyWoed" placeholder="请输入关键字">
         <button @click = "sortType = 1">升序</button>
         <button @click = "sortType = 2">降序</button>
         <button @click = "sortType = 0">原顺序</button>
         <ul>
             <li v-for = " p in filterPersons" :key="p.id">
                 {{p.name}} ----- {{p.age}}
             </li>
         </ul>
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             keyWoed: '',
             sortType: 0,
             persons: [
                 {'id':'10001','name':'紫邪情','age':'18'},
                 {'id':'10002','name':'紫邪晴','age':'14'},
                 {'id':'10003','name':'邪公子','age':'121'},
                 {'id':'10004','name':'公孙策','age':'21'},
                 {'id':'10005','name':'孙悟空','age':'42'}
             ]
         },
 
         computed: {
             filterPersons(){
                 /* 
                     排序:就是将列表过滤之后的数据 根据特定字段排序之后,再渲染到页面中即可
 
                     因此:return this.persons.filter这里不能直接用return,不然就直接把过滤的数据渲染到页面了
                     所以:再对这一步做一下排序操作
                 */
                // 先用个数组装起来
                 const arr =  this.persons.filter( (p)=>{
                     return p.name.indexOf( this.keyWoed ) !== -1;
                 })
 
                 // 然后对数组进行排序操作,但是得先知道用户是点击的哪个按钮( sortType )
                 if (this.sortType) {
                     arr.sort( (previous,last)=>{
                         return this.sortType == 1 ? previous.age - last.age : last.age - previous.age;
                     })
                 }
 
                 return arr;
             }
         }
        });
     </script>
   </body>
 </html>
 

1.15、Vue监视数据的原理

1.15.1、监视数据失效实例

正常版


 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>1 - 监视数据失效实例</title>
 
     <script src="../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>Vue监视数据失效问题</h2>
         <ul>
             <li v-for = "p in persons" :key="p.id">
                 {{p.name}} ---- {{p.age}}
             </li>
         </ul>
 
         <button @click = "update">修改数据</button>
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             persons: [
                 {'id':'10001','name':'紫邪情','age':'18'}
             ]
         },
 
         methods: {
             update(){
                 this.persons[0].name = '紫女';
             }
         }
        });
     </script>
   </body>
 </html>
1.15.2、Vue监视对象的原理
  • 这个数据代理,只是简单了解而已,上面的流程其实不算对,因为少了一个步骤,整个流程应该是:data ————> 对data进行加工 —————> 把data中的数据给_data ————> 再把_data的内容给页面需要的data中( 即:这一步相当于执行了 vm.data = _data , 这个data就是页面上的data嘛,所以就成功地让页面中的数据跟着自己的修改而改变了,但是底层不是用 vm.data = _data,方法名不一样,而且还要更复杂一点

模拟数据监听

 
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>4 - 模拟Vue数据监视</title>
 
   </head>
 
   <body>
     <script>
 
         // 准备一个对象
         let data = {
             name: '紫邪情',
             sex: '女'
         }
 
         // vue做了精妙之一就是:设计了一个构造方法Observer(传对象名),这个东西刚刚在_data中见过它,打开就是用Observer打开的
         function Observer(obj) {
             // 拿到data中的所有key值( 即:上面的name、sex ),放到一个数组里面去
             const keys = Object.keys( obj );
 
             // 遍历这些key值,得到每一个key
             keys.forEach( (key) => {
                 
                 // 使用defineProperty()做数据代理  这里的this就是指:传的对象
                 Object.defineProperty( this, key , {
                     get(){
                         return obj[key];
                     },
 
                     set(val){
                         console.log( "值被修改了,要开始解析数据、生成虚拟DOM、进行对比算法、响应数据了");
                         obj[key] = val;
                     }
                 })
             });
         }
 
         // 调用设计的构造方法,从而开始做 data 转 _data
         const objs = new Observer(data);
         let vm = {};
          vm._data = data = objs
 
         console.log( objs );
 
     </script>
   </body>
 </html>
1.15.3、了解Vue.set( target ,key , val )

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>5 - 了解Vue.set( target, key, val )</title>
 
     <script src="../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2> 姓名: {{person.name}} </h2> <br/>
 
         <h2> 性别: {{person.sex}} </h2> <br/>
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
            person:{
                 name: '紫邪情',
                 sex: '女'
            }
         },
        });
     </script>
   </body>
 </html>

注意

  • target不可以直接指向vm这个实例对象,更不可以把要操作的对象指向data这个根数据对象上
1.15.4、Vue监视数组数据的原理
<!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>1 - 正常实例 - 控制台查看结构</title>
 
     <script src="../../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>爱好</h2>
 
         <ul>
             <li v-for = "(h , index) in hobby" :key="index">
                 <h2> {{h}} </h2>
             </li>
         </ul>
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             hobby: [ '吃', '喝', '嫖', '赌', '要不得']
         },
        });
     </script>
   </body>
 </html>
 

Vue中要监视到数组的变化,调用下面的7个API中的一个就可以

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

总结

  • 1、vue会监视data中所有层级的数据

  • 2、Vue如何监视对象中的数据?

    • 通过setter实现监视,且要在new Vue时就传入要监视的数据
      • (1)、对象中后追加的属性,Vue默认不做响应式处理
      • (2)、如果需要对后添加的属性做响应式,则:通过如下API就可做到
        vue.set( target, key, val ) 说明一下:其中的key可以是属性名,也可以是数组的下标值
        vm.$set( target, key, val ) key和上面一样
  • 3、Vue如何监视数组中的数据?

    • 通过封装 / 包裹数组更新元素的方法来实现,这个封装的方法做了两件事
      • (1)、调用数组原生的同名API,对数组进行更新
      • (2)、重新解析数据、生成新的虚拟DOM、进行对比算法、响应页面
  • 4、在Vue中要修改数组中的某个元素时,只能使用如下的方法

    • (1)、push()、pop()、shift()、unshift()、splice()、sort()、reverse()
    • (2)、vue.set( target, key, val ) 或 vm.$set( target, key, val )
    • 注意:vue.set( target, key, val ) 和 vm.$set( target, key, val ) 不能给vm( 即:vue实例 ) 或 根数据对象data 进行添加属性操作
  • 5、前面分析对象的原理时说过一个流程:
    数据发生改变,是通过setter来获取改变的数据,从而重新解析模板、生成新的虚拟DOM、进行对比算法、响应页面。在这里面有一个重要的流程:就是1、数据改变、setter获取到改变后的值、2、setter重新解析模板,这里1 ——> 2这一步有个专业的词叫做:数据劫持,劫持劫持嘛,半路把东西拿走了呗( 就是setter把数据劫走了,它去做后续的操作 )

1.16、input输入框中v-model的使用技巧

原因:

  • 1、v-model收集的是value值
  • 2、而radio是选择,是使用checked = true / false来做到是否选中的
  • 3、因此:给此种radio类型的input添加一个value属性即可
    v-model的修饰符

事件的修饰符

  • prevent 表示:阻止默认事件的触发

  • stop 表示:阻止事件冒泡

  • once 表示:只执行一次事件

  • v-model也有修饰符:number、lazy、trim

    • (1)、number修饰符,这个修饰符一般都是和input的number类型一起使用的,如:增加一个年龄
    • (2)、lazy修饰符,这个修饰符就光标离开之后再收集数据
    • (3)、trim修饰符,这个在java的String中见过,再熟悉不过了,就是去除前后的空格,不演示了

1.17、过滤器filters

### 1.18、Vue内置指令
回顾一下:已经学了Vue的哪些内置指令
v-onv-bindv-modelv-ifv-else-ifv-elsev-show

另外还有哪些内置指令
v-textv-htmlv-cloakv-oncev-pre

#### 1.18.1、v-text指令
v-text内置指令小结

  • 1、 作用:向其所在的节点中渲染“文本”内容
  • 2、与插值表达式的区别:v-text会替换掉节点中的所有内容,而{{xxx}}插值表达式则不会
1.18.2、v-html内置指令

v-html小结

  • 1、作用:向指定节点中渲染包含html结构的内容
  • 2、与插值表达式的区别
    • 1、v-html会替换掉节点中所有的内容,而插值表达式{{xx}}则不会
    • 2、v-html可以识别html结构
  • 3、特别注意:v-html有安全性问题
    • 1、在网站上动态渲染任意html是非常危险的,容易导致XSS攻击
    • 2、一定要在可信的内容上使用v-html,此指令永远不要用在用户提交的内容上!!!
1.18.3、v-cloak指令

v-cloak指令小结

  • 1、本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
  • 2、使用CSS配合v-cloak指令可以解决网速慢时页面展示出{{xxx}}插值表达式 / axios交互延迟的问题
    • axios就是另类的ajax,甚至和ajax差不多一模一样,而Vue本身并不支持交互,所以才需要借助axios插件来进行交互,这也是玩了Vue之后必须掌握的一个知识点,对于学java的人来说太简单了,上手的话,看一眼就懂了,那就是一个链式调用罢了,就和StringBuilder一样链式调,只是需要传一些东西进去而已,而传的东西在ajax中都见过( 当然:只学了Vue,然后使用ajax一样可以进行数据发送,只是axios更轻小而已 )
1.18.4、v-once指令

v-once指令小结

  • 1、v-once所在节点在初次动态渲染后,就视为静态内容了
  • 2、以后数据的改变不会引起v-once所在结构的更新,可以用来做性能优化
  • 3、注意:和事件修饰符中的once区别开
    • (1)事件中的once修饰符是说的事件( 函数 / js表达式)只执行一次
    • (2)而v-once指令是说的对div容器中的模板只动态渲染一次
1.18.5、v-pre指令

v-pre小结

  • 1、v-pre是跳过其所在节点的编译过程,也就是:原本是什么样子,那么Vue就拿到的是什么样子,不会再去解析它
  • 2、可利用它跳过:没有使用指令语法、没有使用插值表达式的节点,从而加快编译,优化性能
1.18.6、自定义指令
1.18.6.1、函数式定义

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>1 - 函数式定义</title>
 
     <script src="../../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>原来的数值为: {{number}}</h2>
 
         <hr/>
 
         <!-- 使用自定义指令 -->
         <h2> 扩大10倍之后的数值: <span v-big = "number"/> </h2>
 
         <hr/>
 
         <button @click = "number ++"> <h4>number+1</h4></button>
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             number: 10
         },
 
         // 设置自定义指令 - 函数式
         // directives里面是可以写N多个自定义指令的,加了s嘛
         directives: {
 
             /* 
                 element     是自定义指令所在结构的HTML标签元素( 节点 )
                 binding     是模板中自定义指令和HTML元素进行的绑定的信息,在这个绑定中有一些需要的东西
                             注:次绑定和v-bind中的绑定不是一个概念
                             v-bind是指的HTML元素内的"属性"和值的绑定
             */
             big(element , binding){
                 element.innerText = binding.value * 10
             }
         }
        });
     </script>
   </body>
 </html>
 

注意点:上面自定义的指令什么时候会被调用?

  • 1、毫无疑问,HTML元素和自定义指令成功绑定时,自定义指令就会被调用,注意:这句话有坑,待会儿下一种自定义方式就会弄到这句话
    看到的效果就是初始化页面一上来就调用了一次,但是里面的门道不是这样的,成功绑定是什么意思,下一种自定义指令再说明

  • 2、自定义指令所在的模板( Div容器 )被重新解析时会被调用
    别混淆了此种说法:自定义指令所依赖的数据发生改变时就会调用自定义指令,此种说法是错的

1.18.6.2、对象式定义
 
 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>2 - 对象式定义</title>
 
     <script src="../../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
       <!-- 现在做一件事情:模拟lable for标签效果 就是:光标位置锁定 别在意设计好不好-->
       <h2>计数: {{count}}</h2>
       <button @click = "count++">地址: </button>
       <input type="text" v-findfocus:value= "address">
       
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
           count: 1,
           address: '中国大陆'
         },
 
         directives: {
           // 先用函数式来玩一下 注意:自定义指令 多个单词别整驼峰命名啊,识别不了的
           findfocus( node, binding){
             console.log(node , binding);
             node.value = binding.value;
             // 获取焦点
             node.focus();
           }
         }
        });
     </script>
   </body>
 </html>
 

1.18.6.3、自定义指令的两大坑和补充
  • 1、命名的坑
    • (1)、这个坑在前面玩对象式时已经说过了,多个单词的名字别采用驼峰命名,但是:只说了这一点,并没有说正确形式应该怎么命名
    • (2)、采用驼峰命名 多个单词组成的指令名正确形式,采用 - 分隔开,指令定义中回归js原始配置
1.18.6.4 自定义全局指令

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>4 - 全局指令配置</title>
 
     <script src="../../../js/vue.js"></script>
   </head>
 
   <body>
     <!-- 被 vm 实例所控制的区域 -->
     <div id="app">
         <h2>计数: {{count}}</h2>
         <button @click = "count++">地址: </button>
 
         <!-- 正确形式命名 采用 - 分隔开 -->
         <input type="text" v-find-focus:value= "address">
     </div>
 
     <script>
        // 去除浏览器控制台中的警告提示信息
       Vue.config.productionTip = false;
 
       // 定义全局指令 - 对象式
       /* 
             第一个参数  指令名
             第二个参数  配置项( 就是把前面的对象配置{}这个花括号整体搬过来了而已 ),函数式也是一样的
                         只不过函数式需要使用 function给包裹起来而已
       */
       Vue.directive('find-focus',{
             // 1、HTML元素和指令进行绑定时执行的函数
             bind(node, binding){
               node.value = binding.value;
             },
 
             // 2、指令所在元素被插入被解析完毕,插入到页面后执行的函数
             inserted(node, binding){
               node.focus();
             },
 
             // 3、指令所在模板被重新解析时执行的函数
             update(node, binding){
               node.value = binding.value;
             }
         })
 
       /*   // 函数式全局指令
         Vue.directive('find-focus', function(){
             // 1、HTML元素和指令进行绑定时执行的函数
             bind(node, binding){
               node.value = binding.value;
             },
 
             // 2、指令所在元素被插入被解析完毕,插入到页面后执行的函数
             inserted(node, binding){
               node.focus();
             },
 
             // 3、指令所在模板被重新解析时执行的函数
             update(node, binding){
               node.value = binding.value;
             }
         })
  */
       // 创建 vm 实例对象
       const vm = new Vue({
         // 指定控制的区域
         el:'#app',
         data:{
             count: 1,
             address: '中国大陆'
         },
        });
     </script>
   </body>
 </html>
 

小结

  • 1、创建了全局指令之后,就可以摆脱只能在一个div容器中使用前面那种局部指令的缺陷了,也就是:现在可以再开一个div容器,然后在这个新开的div容器中一样可以使用全局配置中的东西
  • 2、全局配置东西基本上都是这么玩的,后续玩组件会用到
1.18.6.5、指令总结
  • 1、定义语法
    • (1)、局部指令
对象式
    new Vue({
        directives: {
            指令名: {
                配置
            }
        }
    })

函数式
    new Vue({
        directives: {
            指令名(){
                配置
            }
        }
    })
  • (2)、全局配置
对象式
Vue.directive( '指令名',{
	配置
})

函数式
Vue.directive('指令名', function(){
	配置
})

  • 2、配置中常用的3个回调
    (1)、bind( element, binding ) 指令与元素成功绑定时调用
    (2)、inserted( element, binding ) 指令所在元素被解析完、插入到页面时调用
    (3)、update( element, binding ) 指令所在模板被重新解析时调用
  • 3、注意项:
    (1)、指令定义时不加 v- ,但使用时必须加 v-
    (2)、指令名如果是多个单词,要使用 - 短横线分隔开,切忌使用驼峰命名( 包括大驼峰和小驼峰 )

1.20、Vue生命周期

1.20.1、了解Vue生命周期的概念
  <!DOCTYPE html>
     <html lang="en">
       <head>
         <meta charset="UTF-8">
         <meta name="viewport" content="width=device-width, initial-scale=1.0">
         <meta http-equiv="X-UA-Compatible" content="ie=edge">
         <title>1 - 认识Vue生命周期概念</title>
 
         <script src="../../js/vue.js"></script>
       </head>
 
       <body>
         <!-- 被 vm 实例所控制的区域 -->
         <div id="app">
             <h2 :style="{opacity: num}">玩动态改变文本透明度</h2>
             {{ change() }}
         </div>
 
         <script>
            // 去除浏览器控制台中的警告提示信息
           Vue.config.productionTip = false;
 
           // 创建 vm 实例对象
           const vm = new Vue({
             // 指定控制的区域
             el:'#app',
             data:{
                 num: 1,
             },
 
             // 改变透明度值大小
             methods: {
                 change(){
                     setInterval(() => {
                         if( this.num <= 0 ) this.num = 1;
 
                         this.num -= 0.01;
                     }, 50);
                 }
             }
            });
         </script>
       </body>
     </html>
 

生命周期过程

Vue生命周期总结

  • 1、定义:Vue在关键时刻帮我们调用的一些特殊名称的函数
  • 2、别名:生命周期回调函数 / 生命周期函数 / 生命周期钩子
  • 3、注意:
    • (1)、生命周期函数的名字不可更改,但是:函数中的执行体是可以自己根据需求编写的
    • (2)、生命周期函数中的this指向是Vue实例 或 组件实例对象
Logo

前往低代码交流专区

更多推荐