当前位置:   article > 正文

Vue.js------vue基础

Vue.js------vue基础
  • 1. 能够了解更新监测, key作用, 虚拟DOM, diff算法
  • 2. 能够掌握设置动态样式
  • 3. 能够掌握过滤器, 计算属性, 侦听器
  • 4. 能够完成品牌管理案例

一.Vue基础_更新监测和key

1.v-for更新监测 

 目标:目标结构变化, 触发v-for的更新 

  • 情况1: 数组翻转
  • 情况2: 数组截取
  • 情况3: 更新值

 口诀:

数组变更方法, 就会导致v-for更新, 页面更新

  • push 方法是 JavaScript 数组对象的一个方法,用于向数组的末尾添加一个或多个新元素,并返回添加新元素后数组的新长度 
  • pop 方法是 JavaScript 数组对象的一个方法,用于移除数组的最后一个元素,并返回被移除的元素。
  • shift 方法是 JavaScript 数组对象的一个方法,用于移除数组的第一个元素,并返回被移除的元素。
  • unshift 方法是 JavaScript 数组对象的一个方法,用于向数组的开头添加一个或多个新元素,并返回添加新元素后数组的新长度。
  • splice 方法是 JavaScript 数组对象的一个方法,用于在指定位置插入或删除元素,并返回被删除的元素组成的数组。
  • sort 方法是 JavaScript 数组对象的一个方法,用于对数组的元素进行排序。默认情况下,sort 方法会将数组的元素转换为字符串,然后按照 Unicode 码点顺序进行排序。
  • reverse 方法是 JavaScript 数组对象的一个方法,用于颠倒数组中元素的顺序,即将数组中的元素从后向前排列。

数组非变更方法, 返回新数组, 就不会导致v-for更新, 可采用覆盖数组或this.$set() 

  • filter 方法可以帮助程序员方便地对数组进行筛选,从而得到符合特定条件的元素集合。

新建一个文件夹,用vscode打开文件,在用命令vue create demo创建项目

 

  1. <template>
  2. <div>
  3. <ul>
  4. <li v-for="(val,index) in arr" :key="index">{{ val }}</li>
  5. </ul>
  6. <button @click="revBtn">数组翻转</button>
  7. <button @click="sliceBtn">截取前三个</button>
  8. <button @click="updateBtn">点击改掉第一个元素的值</button>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. data(){
  14. return {
  15. arr: [5,3,9,2,1]
  16. }
  17. },
  18. methods: {
  19. revBtn(){
  20. // 1.数据翻转可以让v-for更新
  21. this.arr.reverse()
  22. },
  23. sliceBtn(){
  24. // 2.数组slice方法不会造成v-for更新
  25. // slice不会改变原始数组
  26. this.arr.slice(0,3)
  27. // console.log(re)
  28. // 解决v-for更新 ---覆盖原始数组
  29. let newArr = this.arr.slice(0,3)
  30. this.arr = newArr
  31. },
  32. updateBtn(){
  33. // 3.更新某个值的时候,v-for是监测不到的
  34. // this.arr[0] = 1000;
  35. // 解决-This.$set()
  36. // 参数1:更新目标结构
  37. // 参数2:更新位置
  38. // 参数3:更新值
  39. this.$set(this.arr,0,1000)
  40. }
  41. }
  42. }
  43. </script>
  44. <style>
  45. </style>

在截取前三个问题中,如何解决v-for更新,如下图: 

在点击改掉第一个元素的值中,如何解决v-for更新问题,如下: 

1. 哪些数组方法会导致v-for更新页面?

         可以改变原数组的方法

2. 有的数组方法不导致v-for更新页面, 如何处理?

        拿返回的新数组, 直接替换旧数组 this.$set()方法更新某个值  

2.v-for就地更新  

 目标:当数组改变后是如何更新的

旧-虚拟DOM结构:                                          新-虚拟DOM结构:

新旧DOM产生后对比, 然后决定是否复用真实DOM/更新内容

  1. <template>
  2. <div>
  3. <ul>
  4. <li v-for="(val, ind) in arr" :key="ind">{{ val }}</li>
  5. </ul>
  6. <button @click="btn">下标1位置插入新来的</button>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. data(){
  12. return {
  13. arr: ["老大","老二","老三"]
  14. }
  15. },
  16. methods: {
  17. btn(){
  18. this.arr.splice(1,0,'新来的')
  19. }
  20. }
  21. }
  22. </script>
  23. <style>
  24. </style>

 v-for更新时, 是如何操作DOM的?

             循环出新的虚拟DOM结构, 和旧的虚拟DOM

结构对比, 尝试复用标签就地更新内容

 3.真实DOM

目标:在document对象上, 渲染到浏览器上显示的标签 

虚拟DOM  

目标:本质是保存节点信息, 属性和内容的一个JS对象 ,真实DOM属性过多, 遍历耗时

 

目标:在内存中比较变化部分, 然后给真实DOM打补丁(更新)

  1. 内存中生成一样的虚拟DOM结构(==本质是个JS对象==)

    因为真实的DOM属性好几百个, 没办法快速的知道哪个属性改变了

    比如template里标签结构

    1. <template>
    2.    <div id="box">
    3.        <p class="my_p">123</p>
    4.    </div>
    5. </template>

    对应的虚拟DOM结构

    1. const dom = {
    2.    type: 'div',
    3.    attributes: [{id: 'box'}],
    4.    children: {
    5.        type: 'p',
    6.        attributes: [{class: 'my_p'}],
    7.        text: '123'
    8.   }
    9. }
  2. 以后vue数据更新

    • 生成新的虚拟DOM结构

    • 和旧的虚拟DOM结构对比

    • 利用diff算法, 找不不同, 只更新变化的部分(重绘/回流)到页面 - 也叫打补丁

==好处1: 提高了更新DOM的性能(不用把页面全删除重新渲染)==

==好处2: 虚拟DOM只包含必要的属性(没有真实DOM上百个属性)==

1. 虚拟DOM是什么?

本质就是一个JS对象, 保存DOM关键信息

2. 虚拟DOM好处?

      提高DOM更新的性能, 不频繁操作真实DOM,

      在内存中找到变化部分, 再更新真实DOM(打补丁)

3.diff算法  

目标:同级比较-根元素变化-整个dom树删除重建  

旧虚拟DOM

  1. <div id="box">
  2.    <p class="my_p">123</p>
  3. </div>

新虚拟DOM

  1. <ul id="box">
  2.    <li class="my_p">123</li>
  3. </ul>
情况2: 根元素没变, 属性改变, ==元素复用==, 更新属性

旧虚拟DOM

  1. <div id="box">
  2.    <p class="my_p">123</p>
  3. </div>

新虚拟DOM

  1. <div id="myBox" title="标题">
  2.    <p class="my_p">123</p>
  3. </div>

01、第一章webpack+vue基础/1-20 虚拟DOM+Diff算法

1. diff算法如何比较新旧虚拟DOM? 同级比较

2. 根元素变化? 删除重新建立整个DOM树

3. 根元素未变, 属性改变? DOM复用, 只更新属性

4.无key 

目标:从第二个往后更新内容 – 性能不高

 情况3: 根元素没变, 子元素没变, 元素内容改变
无key - 就地更新

v-for不会移动DOM, 而是尝试复用, 就地更新,如果需要v-for移动DOM, 你需要用特殊 attribute key 来提供一个排序提示

  1. <ul id="myUL">
  2.    <li v-for="str in arr">
  3.       {{ str }}
  4.        <input type="text">
  5.    </li>
  6. </ul>
  7. <button @click="addFn">下标为1的位置新增一个</button>
  1. export default {
  2.    data(){
  3.        return {
  4.            arr: ["老大", "新来的", "老二", "老三"]
  5.       }
  6.   },
  7.    methods: {
  8.        addFn(){
  9.            this.arr.splice(1, 0, '新来的')
  10.       }
  11.   }
  12. };

 

目标:最大限度尝试就地修改/复用相同类型元素

有key, 值为索引  

目标:有key属性, 基于key的来比较新旧虚拟DOM, 移除key不存在元素

目标:先产生新旧虚拟DOM, 根据key比较, 还是就地更新  

有key, 值唯一不重复的字符串或数字

目标:有key属性, 基于key的来比较新旧虚拟DOM, 移除key不存在元素

  • 给每个数据换成对象, 准备id, 把id的值作为key  

有key, 值为id

目标:先产生新旧虚拟DOM, 根据key比较

key的值只能是唯一不重复的, 字符串或数值

v-for不会移动DOM, 而是尝试复用, 就地更新,如果需要v-for移动DOM, 你需要用特殊 attribute key 来提供一个排序提示

新DOM里数据的key存在, 去旧的虚拟DOM结构里找到key标记的标签, 复用标签

新DOM里数据的key存在, 去旧的虚拟DOM结构里没有找到key标签的标签, 创建

旧DOM结构的key, 在新的DOM结构里没有了, 则==移除key所在的标签==  

  1. <template>
  2. <div>
  3. <ul>
  4. <li v-for="obj in arr" :key="obj.id">
  5. {{ obj.name }}
  6. <input type="text">
  7. </li>
  8. </ul>
  9. <button @click="btn">下标1位置插入新来的</button>
  10. </div>
  11. </template>
  12. <script>
  13. export default {
  14. data() {
  15. return {
  16. arr: [
  17. {
  18. name: '老大',
  19. id: 50
  20. },
  21. {
  22. name: '老二',
  23. id: 31
  24. },
  25. {
  26. name: '老三',
  27. id: 10
  28. }
  29. ],
  30. };
  31. },
  32. methods: {
  33. btn(){
  34. this.arr.splice(1, 0, {
  35. id: 19,
  36. name: '新来的'
  37. })
  38. }
  39. }
  40. };
  41. </script>
  42. <style>
  43. </style>

1. 子元素或者内容改变会分diff哪2种情况比较?

无key, 就地更新

有key, 按照key比较

2. key值要求是?

唯一不重复的字符串或者数值

3. key应该怎么用?

有id用id, 无id用索引

4. key的好处? 可以配合虚拟DOM提高更新的性能

v-for什么时候会更新页面呢?

           数组采用更新方法, 才导致v-for更新页面

vue是如何提高更新性能的?

         采用虚拟DOM+diff算法提高更新性能

虚拟DOM是什么?

        本质是保存dom关键信息的JS对象
diff算法如何比较新旧虚拟DOM?

       根元素改变 – 删除当前DOM树重新建

       根元素未变, 属性改变 – 更新属性

       根元素未变, 子元素/内容改变

             无key – 就地更新 / 有key – 按key比较

 5.动态class

目标: 用v-bind给标签class设置动态的值

  • 语法 :class="{类名: 布尔值}"  

  1. <template>
  2. <div>
  3. <!-- 语法:
  4. :class="{类名:布尔值}"
  5. 使用场景:vue变量控制标签是否应该有类名-->
  6. <p :class="{red_str: bool}">动态class</p>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. data(){
  12. return {
  13. bool : true
  14. }
  15. },
  16. methods: {
  17. }
  18. }
  19. </script>
  20. <style scoped>
  21. .red_str{
  22. color: red;
  23. }
  24. </style>

如何给标签class属性动态赋值?

       :class=“{类名: 布尔值}”, true使用, false不用

6.动态style  

目标: 给标签动态设置style的值

语法 :style="{css属性名: 值}"

  1. <template>
  2. <div>
  3. <!-- 动态stule语法
  4. :style="{css属性名: 值}" -->
  5. <!-- backgroundColor是一个变量 -->
  6. <!-- <p :style="{backgroundColor: 'red'}">动态class</p> -->
  7. <p :style="{ backgroundColor: color }">动态class</p>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. data(){
  13. return {
  14. color : 'red'
  15. }
  16. },
  17. methods: {
  18. }
  19. }
  20. </script>
  21. <style>
  22. </style>

给style赋值和class区别是?

             :class="{类名: 布尔值}”, true使用, false不用

             :style="{css属性名: 值}"  

7.案例-品牌管理(铺)  

  • 需求1: 把默认数据显示到表格上
  • 需求2: 注意资产超过100的, 都用红色字体标记出来  

  • ① 先铺设静态页面 --- 去.md文档里, 复制数据和标签模板
  • ② 此案例使用bootstrap, 需要下载, 并导入到工程main.js中
  • ③ 用v-for配合默认数据, 把数据默认铺设到表格上显示
  • ④ 直接在标签上, 大于100价格, 动态设置red类名

用到了哪些技术点?

布局用bootstrap, yarn下载引入使用

v-for把数据渲染到表格里

:class动态判断价格给红色类名

 首先使用npm install bootstrap命令下载bootstrap

在main.js中引入bootstrap

  1. <template>
  2. <div id="app">
  3. <div class="container">
  4. <!-- 顶部框模块 -->
  5. <div class="form-group">
  6. <div class="input-group">
  7. <h4>品牌管理</h4>
  8. </div>
  9. </div>
  10. <!-- 数据表格 -->
  11. <table class="table table-bordered table-hover mt-2">
  12. <thead>
  13. <tr>
  14. <th>编号</th>
  15. <th>资产名称</th>
  16. <th>价格</th>
  17. <th>创建时间</th>
  18. <th>操作</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr v-for="obj in list" :key="obj.id">
  23. <td>{{ obj.id }}</td>
  24. <td>{{ obj.name }}</td>
  25. <!-- 如果价格超过100,就有red这个类 -->
  26. <td :class="{ 'red': obj.price > 100 }">{{ obj.price }}</td>
  27. <td>{{ obj.time }}</td>
  28. <td><a href="#">删除</a></td>
  29. </tr>
  30. </tbody>
  31. <!--
  32. <tfoot >
  33. <tr>
  34. <td colspan="5" style="text-align: center">暂无数据</td>
  35. </tr>
  36. </tfoot>
  37. -->
  38. </table>
  39. <!-- 添加资产 -->
  40. <form class="form-inline">
  41. <div class="form-group">
  42. <div class="input-group">
  43. <input type="text" class="form-control" placeholder="资产名称" />
  44. </div>
  45. </div>
  46. &nbsp;&nbsp;&nbsp;&nbsp;
  47. <div class="form-group">
  48. <div class="input-group">
  49. <input type="text" class="form-control" placeholder="价格" />
  50. </div>
  51. </div>
  52. &nbsp;&nbsp;&nbsp;&nbsp;
  53. <!-- 阻止表单提交 -->
  54. <button class="btn btn-primary">添加资产</button>
  55. </form>
  56. </div>
  57. </div>
  58. </template>
  59. <script>
  60. // 1. 明确需求
  61. // 2. 标签+样式+默认数据
  62. // 3. 下载bootstrap, main.js引入bootstrap.css
  63. // 4. 把list数组 - 铺设表格
  64. // 5. 修改价格颜色
  65. export default {
  66. data() {
  67. return {
  68. name: "", // 名称
  69. price: 0, // 价格
  70. list: [
  71. { id: 100, name: "外套", price: 199, time: new Date('2010-08-12') },
  72. { id: 101, name: "裤子", price: 34, time: new Date('2013-09-01') },
  73. { id: 102, name: "鞋", price: 25.4, time: new Date('2018-11-22') },
  74. { id: 103, name: "头发", price: 19900, time: new Date('2020-12-12') }
  75. ],
  76. };
  77. },
  78. };
  79. </script>
  80. <style >
  81. .red {
  82. color: red;
  83. }
  84. </style>

8.案例-品牌管理(增)

品牌数据增加, 功能实现

  • 需求1: 实现表单数据新增进表格功能
  • 需求2: 判断用户输入是否为空给提示

分析

  • ① 添加资产按钮 – 绑定点击事件
  • ② 给表单v-model绑定vue变量收集用户输入内容
  • ③ 添加数组到数组中
  • ④ 判断用户内容是否符合规定
  1. <template>
  2. <div id="app">
  3. <div class="container">
  4. <!-- 顶部框模块 -->
  5. <div class="form-group">
  6. <div class="input-group">
  7. <h4>品牌管理</h4>
  8. </div>
  9. </div>
  10. <!-- 数据表格 -->
  11. <table class="table table-bordered table-hover mt-2">
  12. <thead>
  13. <tr>
  14. <th>编号</th>
  15. <th>资产名称</th>
  16. <th>价格</th>
  17. <th>创建时间</th>
  18. <th>操作</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr v-for="obj in list" :key="obj.id">
  23. <td>{{ obj.id }}</td>
  24. <td>{{ obj.name }}</td>
  25. <!-- 如果价格超过100,就有red这个类 -->
  26. <td :class="{ 'red': obj.price > 100 }">{{ obj.price }}</td>
  27. <td>{{ obj.time }}</td>
  28. <td><a href="#">删除</a></td>
  29. </tr>
  30. </tbody>
  31. <!--
  32. <tfoot >
  33. <tr>
  34. <td colspan="5" style="text-align: center">暂无数据</td>
  35. </tr>
  36. </tfoot>
  37. -->
  38. </table>
  39. <!-- 添加资产 -->
  40. <form class="form-inline">
  41. <div class="form-group">
  42. <div class="input-group">
  43. <input type="text" class="form-control" placeholder="资产名称" v-model="name"/>
  44. </div>
  45. </div>
  46. &nbsp;&nbsp;&nbsp;&nbsp;
  47. <div class="form-group">
  48. <div class="input-group">
  49. <input type="text" class="form-control" placeholder="价格" v-model="price" />
  50. </div>
  51. </div>
  52. &nbsp;&nbsp;&nbsp;&nbsp;
  53. <!-- 阻止表单提交(刷新网页数据又回去了) -->
  54. <button class="btn btn-primary" @click.prevent="addFn">添加资产</button>
  55. </form>
  56. </div>
  57. </div>
  58. </template>
  59. <script>
  60. // 目标:新增
  61. // 1.按钮 - 事件
  62. // 2.给表单v-model绑定vue变量
  63. export default {
  64. data() {
  65. return {
  66. name: "", // 名称
  67. price: 0, // 价格
  68. list: [
  69. { id: 100, name: "外套", price: 199, time: new Date('2010-08-12') },
  70. { id: 101, name: "裤子", price: 34, time: new Date('2013-09-01') },
  71. { id: 102, name: "鞋", price: 25.4, time: new Date('2018-11-22') },
  72. { id: 103, name: "头发", price: 19900, time: new Date('2020-12-12') }
  73. ],
  74. };
  75. },
  76. methods:{
  77. addFn(){
  78. // 5.判断是否为空
  79. if (this.name.trim().length == 0 || this.price === 0){
  80. alert('不能为空')
  81. return
  82. }
  83. // 3.把值以对象形式-插入list
  84. this.list.push({
  85. // 当前数组最后一个对象的id+1作为新对象id值
  86. id: this.list[this.list.length - 1] .id +1,
  87. name: this.name,
  88. price: this.price,
  89. time:new Date()
  90. })
  91. }
  92. }
  93. };
  94. </script>
  95. <style >
  96. .red {
  97. color: red;
  98. }
  99. </style>

涉及到了哪些技术点?

@绑定事件

v-model收集表单数据

.prevent阻止按钮提交表单刷新页面

v-model修饰符 数组取最后一个元素

9.案例-品牌管理(删)  

需求1: 点击删除的a标签, 删除数据

需求2: 删除没数据了要提示暂无数据的tfoot

  • ① a标签绑定点击事件
  • ② 给事件方法传id
  • ③ 通过id, 找到对应数据删除
  • ④ 删除光了要让tfoot显示
  • ⑤ 删除光了再新增, 有bug(id值问题)需要修复
  1. <template>
  2. <div id="app">
  3. <div class="container">
  4. <!-- 顶部框模块 -->
  5. <div class="form-group">
  6. <div class="input-group">
  7. <h4>品牌管理</h4>
  8. </div>
  9. </div>
  10. <!-- 数据表格 -->
  11. <table class="table table-bordered table-hover mt-2">
  12. <thead>
  13. <tr>
  14. <th>编号</th>
  15. <th>资产名称</th>
  16. <th>价格</th>
  17. <th>创建时间</th>
  18. <th>操作</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr v-for="obj in list" :key="obj.id">
  23. <td>{{ obj.id }}</td>
  24. <td>{{ obj.name }}</td>
  25. <!-- 如果价格超过100,就有red这个类 -->
  26. <td :class="{ red: obj.price > 100 }">{{ obj.price }}</td>
  27. <td>{{ obj.time }}</td>
  28. <td><a href="#" @click="delFn(obj.id)">删除</a></td>
  29. </tr>
  30. </tbody>
  31. <tfoot v-show="list.length === 0">
  32. <tr>
  33. <td colspan="5" style="text-align: center">暂无数据</td>
  34. </tr>
  35. </tfoot>
  36. </table>
  37. <!-- 添加资产 -->
  38. <form class="form-inline">
  39. <div class="form-group">
  40. <div class="input-group">
  41. <input type="text" class="form-control" placeholder="资产名称" v-model="name" />
  42. </div>
  43. </div>
  44. &nbsp;&nbsp;&nbsp;&nbsp;
  45. <div class="form-group">
  46. <div class="input-group">
  47. <input type="text" class="form-control" placeholder="价格" v-model.number="price" />
  48. </div>
  49. </div>
  50. &nbsp;&nbsp;&nbsp;&nbsp;
  51. <button class="btn btn-primary" @click.prevent="addFn">添加资产</button>
  52. </form>
  53. </div>
  54. </div>
  55. </template>
  56. <script>
  57. // 目标: 删除功能
  58. // 1. 删除a标签-点击事件
  59. // 2. 对应方法名
  60. // 3. 数据id到事件方法中
  61. // 4. 通过id, 找到这条数据在数组中的下标
  62. // 5. splice方法删除原数组里的对应元素
  63. // 6. 设置tfoot, 无数据给出提示
  64. // 7. 无数据再新增, id要判断一下
  65. export default {
  66. data() {
  67. return {
  68. name: "", // 名称
  69. price: 0, // 价格
  70. list: [
  71. { id: 100, name: "外套", price: 199, time: new Date('2010-08-12') },
  72. { id: 101, name: "裤子", price: 34, time: new Date('2013-09-01') },
  73. { id: 102, name: "鞋", price: 25.4, time: new Date('2018-11-22') },
  74. { id: 103, name: "头发", price: 19900, time: new Date('2020-12-12') }
  75. ],
  76. };
  77. },
  78. methods: {
  79. addFn() {
  80. if (this.name.trim().length === 0 || this.price === 0) {
  81. alert("不能为空")
  82. return
  83. }
  84. // 解决bug: 无数组新增-list没有数据, id需要给一个固定值(以后id都是后台生成, 现在是模拟给一个id)
  85. let id = this.list.length > 0 ? this.list[this.list.length - 1].id + 1 : 100
  86. this.list.push({
  87. // 当前数组最后一个对象的id+1作为新对象id值
  88. id: id,
  89. name: this.name,
  90. price: this.price,
  91. time: new Date()
  92. })
  93. },
  94. delFn(id) {
  95. // 通过id找到这条数据在数组中下标
  96. let index = this.list.findIndex(obj => obj.id === id)
  97. this.list.splice(index, 1)
  98. }
  99. }
  100. };
  101. </script>
  102. <style >
  103. .red {
  104. color: red;
  105. }
  106. </style>

涉及到了哪些技术点?

事件传id

删除数组元素方法

id值判断问题

 二.Vue基础_过滤器

1.过滤器_定义使用

目标: 转换格式, 过滤器就是一个函数, 传入值返回处理后的值

过滤器只能用在, 插值表达式和v-bind动态属性里

Vue中的过滤器场景

  • 字符串翻转, "输入hello, world", 输出"dlrow ,olleh”
  • 字母转大写, 输入"hello", 输出"HELLO”

语法:

  • Vue.filter("过滤器名", (值) => {return "返回处理后的值"})
  • filters: {过滤器名字: (值) => {return "返回处理后的值"}

  1. <template>
  2. <div>
  3. <p>原来的样子:{{ msg }}</p>
  4. <!-- 2.过滤器使用
  5. 语法: {{ 值 | 过滤器名字 }} -->
  6. <p>使用翻转过滤器: {{ msg | reverse }}</p>
  7. <p :title="msg | toUp">鼠标长度</p>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. data(){
  13. return {
  14. msg: 'Hello, Vue'
  15. }
  16. },
  17. // 方式2:局部 - 过滤器
  18. // 只能在当前vue文件内使用
  19. /*
  20. 语法:
  21. filters:{
  22. 过滤器名字(val){
  23. return 处理后的值
  24. }
  25. }
  26. */
  27. filters:{
  28. toUp(val){
  29. return val.toUpperCase()
  30. }
  31. }
  32. }
  33. </script>
  34. <style>
  35. </style>

第三个是鼠标悬浮的时候会出现翻转 

 1. Vue中过滤器作用?

            传入一个值, 处理后返回另外一个值

2. 如何定义过滤器?

           main.js – Vue.filter('过滤器名字', 函数体)

           某.vue文件 – filters: {'过滤器名字': 函数体}

3. 如何使用过滤器? Vue变量 | 过滤器名字

4. 过滤器注意事项? 插值表达式 / 动态属性

2.过滤器_传参和多过滤器  

目标: 可同时使用多个过滤器, 或者给过滤器传参

语法:

  • 过滤器传参: vue变量 | 过滤器(实参)
  • 多个过滤器: vue变量 | 过滤器1 | 过滤器2

  1. <template>
  2. <div>
  3. <p>原来的样子:{{ msg }}</p>
  4. <!-- 1.给过滤器传参
  5. 语法:vue变量 | 过滤器名(值)
  6. -->
  7. <p>使用翻转过滤器: {{ msg | reverse('|') }}</p>
  8. <!-- 2.
  9. 多个过滤利使用
  10. 语法:vue变量 | 过滤器1 | 过滤器2 -->
  11. <p :title="msg | toUp | reverse('|')">鼠标长度</p>
  12. </div>
  13. </template>
  14. <script>
  15. export default {
  16. data() {
  17. return {
  18. msg: 'Hello, Vue'
  19. }
  20. },
  21. filters: {
  22. toUp(val) {
  23. return val.toUpperCase()
  24. }
  25. }
  26. }
  27. </script>
  28. <style></style>

 点击第三个会出现右图所出现的

 

 1. 多个过滤器使用?

      vue变量 | 过滤器1 | 过滤器2

2. 如何给过滤器传额外值

         vue变量 | 过滤器(值)

3.案例-品牌管理(时间格式化) 

 需求: 表格里的时间用过滤器+moment模块, 格式化成YYYY-MM-DD 格式

  • ① 下载moment模块到当前工程
  • ② 定义过滤器, 传入时间, 用moment模块格式化, 返回我们想要的格式

涉及到了哪些技术点?

yarn下包

过滤器定义和使用

moment复习

先使用npm install moment 下载moment

 

在main.js中引入moment

  1. <template>
  2. <div id="app">
  3. <div class="container">
  4. <!-- 顶部框模块 -->
  5. <div class="form-group">
  6. <div class="input-group">
  7. <h4>品牌管理</h4>
  8. </div>
  9. </div>
  10. <!-- 数据表格 -->
  11. <table class="table table-bordered table-hover mt-2">
  12. <thead>
  13. <tr>
  14. <th>编号</th>
  15. <th>资产名称</th>
  16. <th>价格</th>
  17. <th>创建时间</th>
  18. <th>操作</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr v-for="obj in list" :key="obj.id">
  23. <td>{{ obj.id }}</td>
  24. <td>{{ obj.name }}</td>
  25. <!-- 如果价格超过100,就有red这个类 -->
  26. <td :class="{red: obj.price > 100}">{{ obj.price }}</td>
  27. <!-- 3. 使用过滤器 -->
  28. <td>{{ obj.time | formatDate }}</td>
  29. <td><a href="#" @click="delFn(obj.id)">删除</a></td>
  30. </tr>
  31. </tbody>
  32. <tfoot v-show="list.length === 0">
  33. <tr>
  34. <td colspan="5" style="text-align: center">暂无数据</td>
  35. </tr>
  36. </tfoot>
  37. </table>
  38. <!-- 添加资产 -->
  39. <form class="form-inline">
  40. <div class="form-group">
  41. <div class="input-group">
  42. <input
  43. type="text"
  44. class="form-control"
  45. placeholder="资产名称"
  46. v-model="name"
  47. />
  48. </div>
  49. </div>
  50. &nbsp;&nbsp;&nbsp;&nbsp;
  51. <div class="form-group">
  52. <div class="input-group">
  53. <input
  54. type="text"
  55. class="form-control"
  56. placeholder="价格"
  57. v-model.number="price"
  58. />
  59. </div>
  60. </div>
  61. &nbsp;&nbsp;&nbsp;&nbsp;
  62. <button class="btn btn-primary" @click.prevent="addFn">添加资产</button>
  63. </form>
  64. </div>
  65. </div>
  66. </template>
  67. <script>
  68. // 目标: 处理时间
  69. // 1. 下载moment模块
  70. import moment from 'moment'
  71. export default {
  72. data() {
  73. return {
  74. name: "", // 名称
  75. price: 0, // 价格
  76. list: [
  77. { id: 100, name: "外套", price: 199, time: new Date('2010-08-12')},
  78. { id: 101, name: "裤子", price: 34, time: new Date('2013-09-01') },
  79. { id: 102, name: "鞋", price: 25.4, time: new Date('2018-11-22') },
  80. { id: 103, name: "头发", price: 19900, time: new Date('2020-12-12') }
  81. ],
  82. };
  83. },
  84. methods: {
  85. addFn(){
  86. if (this.name.trim().length === 0 || this.price === 0) {
  87. alert("不能为空")
  88. return
  89. }
  90. // 解决bug: 无数组新增-list没有数据, id需要给一个固定值(以后id都是后台生成, 现在是模拟给一个id)
  91. let id = this.list.length > 0 ? this.list[this.list.length - 1].id + 1 : 100
  92. this.list.push({
  93. // 当前数组最后一个对象的id+1作为新对象id值
  94. id: id,
  95. name: this.name,
  96. price: this.price,
  97. time: new Date()
  98. })
  99. },
  100. delFn(id){
  101. // 通过id找到这条数据在数组中下标
  102. let index = this.list.findIndex(obj => obj.id === id)
  103. this.list.splice(index, 1)
  104. }
  105. },
  106. // 2. 定义过滤器, 编写内部代码
  107. filters: {
  108. formatDate (val){
  109. return moment(val).format('YYYY-MM-DD')
  110. }
  111. }
  112. };
  113. </script>
  114. <style >
  115. .red{
  116. color: red;
  117. }
  118. </style>

三.Vue基础_计算属性

1.计算属性_computed  

目标: 一个变量的值, 依赖另外一些数据计算而来的结果

注意: 计算属性也是vue数据变量, 所以不要和data里重名, 用法和data相同

  1. <template>
  2. <div>
  3. <p>{{ num }}</p>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. data(){
  9. return {
  10. a: 10,
  11. b: 20
  12. }
  13. },
  14. // 计算属性
  15. // 场景:一个变量的值,需要用另外变量计算而得来
  16. /*
  17. 语法:
  18. computed:{
  19. 计算属性名(){
  20. retturn 值
  21. }
  22. }
  23. */
  24. computed:{
  25. num(){
  26. return this.a + this.b
  27. }
  28. }
  29. }
  30. </script>
  31. <style>
  32. </style>

 

1. 计算属性使用场景?

            当变量的值, 需要通过别人计算而得来

2. 计算属性特点?

           函数内使用的变量改变, 重新计算结果返回

3. 计算属性注意事项?

          计算属性名和data里名字不能重复

2.计算属性_缓存  

目标: 计算属性, 基于依赖项的值进行缓存,依赖的变量不变, 都直接从缓存取结果

 

  1. <template>
  2. <div>
  3. <p>{{ reverseMessage }}</p>
  4. <p>{{ reverseMessage }}</p>
  5. <p>{{ reverseMessage }}</p>
  6. <p>{{ getMessage() }}</p>
  7. <p>{{ getMessage() }}</p>
  8. <p>{{ getMessage() }}</p>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. data(){
  14. return {
  15. msg: "Hello, Vue"
  16. }
  17. },
  18. // 计算属性优势:
  19. // 带缓存
  20. // 计算属性对应函数执行后,会把return值缓存起来
  21. // 依赖项不变,多次调用都是从缓存取值
  22. // 依赖项值-变化,函数会"自动"重新执行-并缓存新的值
  23. computed:{
  24. reverseMessage(){
  25. console.log("计算属性执行了")
  26. return this.msg.split("").reverse().join("")
  27. }
  28. },
  29. methods: {
  30. getMessage(){
  31. console.log("函数执行了")
  32. return this.msg.split("").reverse().join("")
  33. }
  34. }
  35. }
  36. </script>
  37. <style>
  38. </style>

1. 计算属性好处是?

带缓存

依赖项不变, 直接从缓存取

依赖项改变, 函数自动执行并重新缓存

2. 计算属性使用场景?

当变量值, 依赖其他变量计算而得来才用

3.案例-品牌管理(总价和均价)  

完成总价和均价的显示结果

需求: 完成商品总价和均价的数据显示功能

分析:

  • ① tbody最后新增一行tr
  • ② 定义总价和均价2个计算属性, 在函数里编写计算过程返回结果
  • ③ 把计算属性用到相应标签处
  1. <template>
  2. <div id="app">
  3. <div class="container">
  4. <!-- 顶部框模块 -->
  5. <div class="form-group">
  6. <div class="input-group">
  7. <h4>品牌管理</h4>
  8. </div>
  9. </div>
  10. <!-- 数据表格 -->
  11. <table class="table table-bordered table-hover mt-2">
  12. <thead>
  13. <tr>
  14. <th>编号</th>
  15. <th>资产名称</th>
  16. <th>价格</th>
  17. <th>创建时间</th>
  18. <th>操作</th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr v-for="obj in list" :key="obj.id">
  23. <td>{{ obj.id }}</td>
  24. <td>{{ obj.name }}</td>
  25. <!-- 如果价格超过100,就有red这个类 -->
  26. <td :class="{ red: obj.price > 100 }">{{ obj.price }}</td>
  27. <td>{{ obj.time | formatDate }}</td>
  28. <td><a href="#" @click="delFn(obj.id)">删除</a></td>
  29. </tr>
  30. <tr style="background-color: #eee">
  31. <td>统计:</td>
  32. <td colspan="2">总价钱为: {{ allPrice }}</td>
  33. <td colspan="2">平均价: {{ avgPrice }}</td>
  34. </tr>
  35. </tbody>
  36. <tfoot v-show="list.length === 0">
  37. <tr>
  38. <td colspan="5" style="text-align: center">暂无数据</td>
  39. </tr>
  40. </tfoot>
  41. </table>
  42. <!-- 添加资产 -->
  43. <form class="form-inline">
  44. <div class="form-group">
  45. <div class="input-group">
  46. <input type="text" class="form-control" placeholder="资产名称" v-model="name" />
  47. </div>
  48. </div>
  49. &nbsp;&nbsp;&nbsp;&nbsp;
  50. <div class="form-group">
  51. <div class="input-group">
  52. <input type="text" class="form-control" placeholder="价格" v-model.number="price" />
  53. </div>
  54. </div>
  55. &nbsp;&nbsp;&nbsp;&nbsp;
  56. <button class="btn btn-primary" @click.prevent="addFn">添加资产</button>
  57. </form>
  58. </div>
  59. </div>
  60. </template>
  61. <script>
  62. // 目标: 总价和均价显示
  63. // 1. 末尾补tr - 显示总价和均价
  64. import moment from 'moment'
  65. export default {
  66. data() {
  67. return {
  68. name: "", // 名称
  69. price: 0, // 价格
  70. list: [
  71. { id: 100, name: "外套", price: 199, time: new Date('2010-08-12') },
  72. { id: 101, name: "裤子", price: 34, time: new Date('2013-09-01') },
  73. { id: 102, name: "鞋", price: 25.4, time: new Date('2018-11-22') },
  74. { id: 103, name: "头发", price: 19900, time: new Date('2020-12-12') }
  75. ],
  76. };
  77. },
  78. methods: {
  79. addFn() {
  80. if (this.name.trim().length === 0 || this.price === 0) {
  81. alert("不能为空")
  82. return
  83. }
  84. // 解决bug: 无数组新增-list没有数据, id需要给一个固定值(以后id都是后台生成, 现在是模拟给一个id)
  85. let id = this.list.length > 0 ? this.list[this.list.length - 1].id + 1 : 100
  86. this.list.push({
  87. // 当前数组最后一个对象的id+1作为新对象id值
  88. id: id,
  89. name: this.name,
  90. price: this.price,
  91. time: new Date()
  92. })
  93. },
  94. delFn(id) {
  95. // 通过id找到这条数据在数组中下标
  96. let index = this.list.findIndex(obj => obj.id === id)
  97. this.list.splice(index, 1)
  98. }
  99. },
  100. filters: {
  101. formatDate(val) {
  102. return moment(val).format("YYYY-MM-DD");
  103. },
  104. },
  105. // 2. 计算属性
  106. computed: {
  107. allPrice() {
  108. // 3. 求总价
  109. return this.list.reduce((sum, obj) => sum += obj.price, 0)
  110. },
  111. avgPrice() {
  112. // 4. 求均价 - 保留2位小数
  113. return (this.allPrice / this.list.length).toFixed(2)
  114. }
  115. }
  116. };
  117. </script>
  118. <style >
  119. .red {
  120. color: red;
  121. }
  122. </style>

涉及到的知识点?

              computed定义和使用计算属性

              数组reduce方法累积运算  

4.计算属性_完整写法

目标: 计算属性也是变量

 

网页输入的值无法传到后端上 

 

  1. <template>
  2. <div>
  3. <span>姓名:</span>
  4. <input type="text" v-model="full">
  5. </div>
  6. </template>
  7. <script>
  8. // 问题:给计算属性赋值 - 需要setter
  9. // 解决:
  10. /*
  11. 完整语法:
  12. computed:{
  13. "计算属性名" (){},
  14. "计算属性名":{
  15. set(值){
  16. },
  17. get(){
  18. return 值
  19. }
  20. }
  21. }
  22. */
  23. export default {
  24. data(){
  25. return {
  26. }
  27. },
  28. computed:{
  29. full:{
  30. // 给full赋值触发set方法
  31. set(val){
  32. console.log(val);
  33. },
  34. // 使用full赋值触发get方法
  35. get(){
  36. return "无名氏"
  37. }
  38. }
  39. }
  40. }
  41. </script>
  42. <style>
  43. </style>

 

1. 何时用计算属性完整写法?

      给计算属性变量赋值时

2. set函数和get函数什么执行?

      set接收要赋予的值

      get里要返回给这个计算属性具体值

5.案例-小选影响全选  

 需求: 小选框都选中(手选), 全选自动选中

分析:

  • ① 先静态后动态, 从.md拿到静态标签和数据
  • ② 循环生成复选框和文字, 对象的c属性和小选框的选中状态, 用v-model双向绑定
  • ③ 定义isAll计算属性, 值通过小选框们统计c属性状态得来

小选框如何影响全选框选中状态的?

        v-model给全选框绑定isAll计算属性

        isAll计算属性里返回统计小选框选中状态结果

 

6.案例-全选影响小选  

  • 需求1: 获取到全选状态 – 改装isAll计算属性
  • 需求2: 全选状态同步给所有小选框  

分析:

  • ①: isAll改成完整写法, set里获取到全选框, 勾选的状态值
  • ②: 遍历数据数组, 赋给所有小选框v-model关联的属性

全选如何影响小选框选中状态的?

         小选框v-model, 关联数组里对象的c属性

         isAll计算属性的set方法, 拿到全选框状态

        状态值赋给, 数组里每个对象的c属性

7.案例-反选  

需求: 点击反选, 让所有小选框, 各自取相反勾选状态

分析:

  • ①: 小选框的勾选状态, 在对象的c属性
  • ②: 遍历所有对象, 把对象的c属性取相反值赋予回去即可

反选如何实现的? 遍历每个对象, 把c属性的值取反再赋予回去

  1. <template>
  2. <div>
  3. <span>全选:</span>
  4. <!-- 4. v-model 关联全选 - 选中状态 -->
  5. <input type="checkbox" v-model="isAll" />
  6. <button @click="btn">反选</button>
  7. <ul>
  8. <li v-for="(obj, index) in arr" :key="index">
  9. <!-- 3. 对象.c - 关联 选中状态 -->
  10. <input type="checkbox" v-model="obj.c" />
  11. <span>{{ obj.name }}</span>
  12. </li>
  13. </ul>
  14. </div>
  15. </template>
  16. <script>
  17. // 目标: 小选框 -> 全选
  18. // 1. 标签+样式+js准备好
  19. // 2. 把数据循环展示到页面上
  20. export default {
  21. data() {
  22. return {
  23. arr: [
  24. {
  25. name: "猪八戒",
  26. c: false,
  27. },
  28. {
  29. name: "孙悟空",
  30. c: false,
  31. },
  32. {
  33. name: "唐僧",
  34. c: false,
  35. },
  36. {
  37. name: "白龙马",
  38. c: false,
  39. },
  40. ],
  41. };
  42. },
  43. // 5. 计算属性-isAll
  44. computed: {
  45. isAll: {
  46. set(val) {
  47. // 7. 全选框 - 选中状态(true/false)
  48. this.arr.forEach(obj => obj.c = val)
  49. },
  50. get() {
  51. // 6. 统计小选框状态 -> 全选状态
  52. // every口诀: 查找数组里"不符合"条件, 直接原地返回false
  53. return this.arr.every(obj => obj.c === true)
  54. }
  55. }
  56. },
  57. methods: {
  58. btn() {
  59. // 8. 让数组里对象的c属性取反再赋予回去
  60. this.arr.forEach(obj => obj.c = !obj.c)
  61. }
  62. }
  63. };
  64. </script>
  65. <style></style>

 

四.Vue基础_侦听器

1.侦听器_watch

 目标: 可以侦听data/computed属性值的改变

如何侦听到某个变量值改变呢? 使用watch配置项, key是要侦听的data/计算属性名 

2.侦听器_深度侦听和立即执行  

目标: 侦听复杂类型, 或者立即执行侦听函数

 

1. 如何侦听一个对象/数组呢? 把侦听器写成对象形式, 给handler方法和deep:true

2. 侦听器函数马上执行?  immediate: true

 

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

闽ICP备14008679号