【前端Vue】day04

打印 上一主题 下一主题

主题 874|帖子 874|积分 2622

一、学习目标

1.组件的三大组成部分(结构/样式/逻辑)

​ scoped办理样式冲突/data是一个函数
2.组件通讯


  • 组件通讯语法
  • 父传子
  • 子传父
  • 非父子通讯(扩展)
3.综合案例:小黑记事本(组件版)


  • 拆分组件
  • 列表渲染
  • 数据添加
  • 数据删除
  • 列表统计
  • 清空
  • 长期化
4.进阶语法


  • v-model原理
  • v-model应用于组件
  • sync修饰符
  • ref和$refs
  • $nextTick
二、scoped办理样式冲突

1.默认情况

写在组件中的样式会 全局生效 → 因此很轻易造成多个组件之间的样式冲突问题。

  • 全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响
  • 局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件
2.代码演示

BaseOne.vue
  1. <template>
  2.   <div class="base-one">
  3.     BaseOne
  4.   </div>
  5. </template>
  6. <script>
  7. export default {
  8. }
  9. </script>
  10. <style scoped>
  11. </style>
复制代码
BaseTwo.vue
  1. <template>
  2.   <div class="base-one">
  3.     BaseTwo
  4.   </div>
  5. </template>
  6. <script>
  7. export default {
  8. }
  9. </script>
  10. <style scoped>
  11. </style>
复制代码
App.vue
  1. <template>
  2.   <div id="app">
  3.     <BaseOne></BaseOne>
  4.     <BaseTwo></BaseTwo>
  5.   </div>
  6. </template>
  7. <script>
  8. import BaseOne from './components/BaseOne'
  9. import BaseTwo from './components/BaseTwo'
  10. export default {
  11.   name: 'App',
  12.   components: {
  13.     BaseOne,
  14.     BaseTwo
  15.   }
  16. }
  17. </script>
复制代码
3.scoped原理


  • 当前组件内标签都被添加data-v-hash值 的属性
  • css选择器都被添加 [data-v-hash值] 的属性选择器
终极结果: 必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到

4.总结


  • style的默认样式是作用到那里的?
  • scoped的作用是什么?
  • style中推不保举加scoped?
三、data必须是一个函数

1、data为什么要写成函数

一个组件的 data 选项必须是一个函数。目标是为了:保证每个组件实例,维护独立的一份数据对象。
每次创建新的组件实例,都会新执行一次data 函数,得到一个新对象。

2.代码演示

BaseCount.vue
  1. <template>
  2.   <div class="base-count">
  3.     <button @click="count--">-</button>
  4.     <span>{{ count }}</span>
  5.     <button @click="count++">+</button>
  6.   </div>
  7. </template>
  8. <script>
  9. export default {
  10.   data: function () {
  11.     return {
  12.       count: 100,
  13.     }
  14.   },
  15. }
  16. </script>
  17. <style>
  18. .base-count {
  19.   margin: 20px;
  20. }
  21. </style>
复制代码
App.vue
  1. <template>
  2.   <div class="app">
  3.     <BaseCount></BaseCount>
  4.   </div>
  5. </template>
  6. <script>
  7. import BaseCount from './components/BaseCount'
  8. export default {
  9.   components: {
  10.     BaseCount,
  11.   },
  12. }
  13. </script>
  14. <style>
  15. </style>
复制代码
3.总结

data写成函数的目标是什么?
四、组件通讯

1.什么是组件通讯?

组件通讯,就是指组件与组件之间的数据传递


  • 组件的数据是独立的,无法直接访问其他组件的数据。
  • 想使用其他组件的数据,就须要组件通讯
2.组件之间如何通讯


思考:

  • 组件之间有哪些关系?
  • 对应的组件通讯方案有哪几类?
3.组件关系分类


  • 父子关系
  • 非父子关系

4.通讯办理方案


5.父子通讯流程


  • 父组件通过 props 将数据传递给子组件
  • 子组件使用 $emit 通知父组件修改更新

6.父向子通讯代码示例

父组件通过props将数据传递给子组件
父组件App.vue
  1. <template>
  2.   <div class="app" style="border: 3px solid #000; margin: 10px">
  3.     我是APP组件
  4.     <Son></Son>
  5.   </div>
  6. </template>
  7. <script>
  8. import Son from './components/Son.vue'
  9. export default {
  10.   name: 'App',
  11.   data() {
  12.     return {
  13.       myTitle: '学前端,就来黑马程序员',
  14.     }
  15.   },
  16.   components: {
  17.     Son,
  18.   },
  19. }
  20. </script>
  21. <style>
  22. </style>
复制代码
子组件Son.vue
  1. <template>
  2.   <div class="son" style="border:3px solid #000;margin:10px">
  3.     我是Son组件
  4.   </div>
  5. </template>
  6. <script>
  7. export default {
  8.   name: 'Son-Child',
  9. }
  10. </script>
  11. <style>
  12. </style>
复制代码

父向子传值步骤

  • 给子组件以添加属性的方式传值
  • 子组件内部通过props接收
  • 模板中直接使用 props接收的值
7.子向父通讯代码示例

子组件使用 $emit 通知父组件,进行修改更新

子向父传值步骤

  • $emit触发变乱,给父组件发送消息通知
  • 父组件监听$emit触发的变乱
  • 提供处理函数,在函数的性参中获取传过来的参数
8.总结


  • 组件关系分类有哪两种
  • 父子组件通讯的流程是什么?

    • 父向子
    • 子向父

五、什么是props

1.Props 定义

组件上 注册的一些 自定义属性
2.Props 作用

向子组件传递数据
3.特点


  • 可以 传递 恣意数量 的prop
  • 可以 传递 恣意类型 的prop

4.代码演示

父组件App.vue
  1. <template>
  2.   <div class="app">
  3.     <UserInfo
  4.       :username="username"
  5.       :age="age"
  6.       :isSingle="isSingle"
  7.       :car="car"
  8.       :hobby="hobby"
  9.     ></UserInfo>
  10.   </div>
  11. </template>
  12. <script>
  13. import UserInfo from './components/UserInfo.vue'
  14. export default {
  15.   data() {
  16.     return {
  17.       username: '小帅',
  18.       age: 28,
  19.       isSingle: true,
  20.       car: {
  21.         brand: '宝马',
  22.       },
  23.       hobby: ['篮球', '足球', '羽毛球'],
  24.     }
  25.   },
  26.   components: {
  27.     UserInfo,
  28.   },
  29. }
  30. </script>
  31. <style>
  32. </style>
复制代码
子组件UserInfo.vue
  1. <template>
  2.   <div class="userinfo">
  3.     <h3>我是个人信息组件</h3>
  4.     <div>姓名:</div>
  5.     <div>年龄:</div>
  6.     <div>是否单身:</div>
  7.     <div>座驾:</div>
  8.     <div>兴趣爱好:</div>
  9.   </div>
  10. </template>
  11. <script>
  12. export default {
  13.   
  14. }
  15. </script>
  16. <style>
  17. .userinfo {
  18.   width: 300px;
  19.   border: 3px solid #000;
  20.   padding: 20px;
  21. }
  22. .userinfo > div {
  23.   margin: 20px 10px;
  24. }
  25. </style>
复制代码
六、props校验

1.思考

组件的props可以乱传吗
2.作用

为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示 → 帮助开发者,快速发现错误
3.语法



  • 类型校验
  • 非空校验
  • 默认值
  • 自定义校验

4.代码演示

App.vue
  1. <template>
  2.   <div class="app">
  3.     <BaseProgress :w="width"></BaseProgress>
  4.   </div>
  5. </template>
  6. <script>
  7. import BaseProgress from './components/BaseProgress.vue'
  8. export default {
  9.   data() {
  10.     return {
  11.       width: 30,
  12.     }
  13.   },
  14.   components: {
  15.     BaseProgress,
  16.   },
  17. }
  18. </script>
  19. <style>
  20. </style>
复制代码
BaseProgress.vue
  1. <template>
  2.   <div class="base-progress">
  3.     <div class="inner" :style="{ width: w + '%' }">
  4.       <span>{{ w }}%</span>
  5.     </div>
  6.   </div>
  7. </template>
  8. <script>
  9. export default {
  10.   props: ['w'],
  11. }
  12. </script>
  13. <style scoped>
  14. .base-progress {
  15.   height: 26px;
  16.   width: 400px;
  17.   border-radius: 15px;
  18.   background-color: #272425;
  19.   border: 3px solid #272425;
  20.   box-sizing: border-box;
  21.   margin-bottom: 30px;
  22. }
  23. .inner {
  24.   position: relative;
  25.   background: #379bff;
  26.   border-radius: 15px;
  27.   height: 25px;
  28.   box-sizing: border-box;
  29.   left: -3px;
  30.   top: -2px;
  31. }
  32. .inner span {
  33.   position: absolute;
  34.   right: 0;
  35.   top: 26px;
  36. }
  37. </style>
复制代码
七、props校验完整写法

1.语法

  1. props: {
  2.   校验的属性名: {
  3.     type: 类型,  // Number String Boolean ...
  4.     required: true, // 是否必填
  5.     default: 默认值, // 默认值
  6.     validator (value) {
  7.       // 自定义校验逻辑
  8.       return 是否通过校验
  9.     }
  10.   }
  11. },
复制代码
2.代码实例

  1. <script>
  2. export default {
  3.   // 完整写法(类型、默认值、非空、自定义校验)
  4.   props: {
  5.     w: {
  6.       type: Number,
  7.       //required: true,
  8.       default: 0,
  9.       validator(val) {
  10.         // console.log(val)
  11.         if (val >= 100 || val <= 0) {
  12.           console.error('传入的范围必须是0-100之间')
  13.           return false
  14.         } else {
  15.           return true
  16.         }
  17.       },
  18.     },
  19.   },
  20. }
  21. </script>
复制代码
3.注意

1.default和required一般差别时写(因为当时必填项时,肯定是有值的)
2.default后面如果是简朴类型的值,可以直接写默认。如果是复杂类型的值,则须要以函数的形式return一个默认值
八、props&data、单向数据流

1.共同点

都可以给组件提供数据
2.区别



  • data 的数据是自己的 → 随便改
  • prop 的数据是外部的 → 不能直接改,要遵循 单向数据流
3.单向数据流:

父级props 的数据更新,会向卑鄙动,影响子组件。这个数据活动是单向的
4.代码演示

App.vue
  1. <template>
  2.   <div class="app">
  3.     <BaseCount></BaseCount>
  4.   </div>
  5. </template>
  6. <script>
  7. import BaseCount from './components/BaseCount.vue'
  8. export default {
  9.   components:{
  10.     BaseCount
  11.   },
  12.   data(){
  13.   },
  14. }
  15. </script>
  16. <style>
  17. </style>
复制代码
BaseCount.vue
  1. <template>
  2.   <div class="base-count">
  3.     <button @click="count--">-</button>
  4.     <span>{{ count }}</span>
  5.     <button @click="count++">+</button>
  6.   </div>
  7. </template>
  8. <script>
  9. export default {
  10.   // 1.自己的数据随便修改  (谁的数据 谁负责)
  11.    data () {
  12.      return {
  13.        count: 100,
  14.      }
  15.    },
  16.   // 2.外部传过来的数据 不能随便修改
  17.   //props: {
  18.   //  count: {
  19.   //    type: Number,
  20.   //  },
  21.   //}
  22. }
  23. </script>
  24. <style>
  25. .base-count {
  26.   margin: 20px;
  27. }
  28. </style>
复制代码

5.口诀

谁的数据谁负责
九、综合案例-组件拆分

1.需求说明



  • 拆分基础组件
  • 渲染待办任务
  • 添加任务
  • 删除任务
  • 底部合计 和 清空功能
  • 长期化存储
2.拆分基础组件

咱们可以把小黑记事本原有的结构拆成三部分内容:头部(TodoHeader)、列表(TodoMain)、底部(TodoFooter)

十、综合案例-列表渲染

思绪分析:

  • 提供数据:提供在公共的父组件 App.vue
  • 通过父传子,将数据传递给TodoMain
  • 使用v-for进行渲染
十一、综合案例-添加功能

思绪分析:

  • 收集表单数据 v-model
  • 监听时间 (回车+点击 都要进行添加)
  • 子传父,将任务名称传递给父组件App.vue
  • 父组件接受到数据后 进行添加 unshift(自己的数据自己负责)
十二、综合案例-删除功能

思绪分析:

  • 监听时间(监听删除的点击)携带id
  • 子传父,将删除的id传递给父组件App.vue
  • 进行删除 filter (自己的数据自己负责)
十三、综合案例-底部功能及长期化存储

思绪分析:

  • 底部合计:父组件传递list到底部组件 —>展示合计
  • 清空功能:监听变乱 —> 子组件通知父组件 —>父组件清空
  • 长期化存储:watch监听数据变化,长期化到本地
十四、非父子通讯-event bus 变乱总线

1.作用

非父子组件之间,进行简易消息传递。(复杂场景→ Vuex)
2.步骤


  • 创建一个都能访问的变乱总线 (空Vue实例)
    1. import Vue from 'vue'
    2. const Bus = new Vue()
    3. export default Bus
    复制代码
  • A组件(接受方),监听Bus的 $on变乱
    1. created () {
    2.   Bus.$on('sendMsg', (msg) => {
    3.     this.msg = msg
    4.   })
    5. }
    复制代码
  • B组件(发送方),触发Bus的$emit变乱
    1. Bus.$emit('sendMsg', '这是一个消息')
    复制代码

3.代码示例

EventBus.js
  1. import Vue from 'vue'
  2. const Bus  =  new Vue()
  3. export default Bus
复制代码
BaseA.vue(接受方)
  1. <template>
  2.   <div class="base-a">
  3.     我是A组件(接收方)
  4.     <p>{{msg}}</p>  
  5.   </div>
  6. </template>
  7. <script>
  8. import Bus from '../utils/EventBus'
  9. export default {
  10.   data() {
  11.     return {
  12.       msg: '',
  13.     }
  14.   },
  15. }
  16. </script>
  17. <style scoped>
  18. .base-a {
  19.   width: 200px;
  20.   height: 200px;
  21.   border: 3px solid #000;
  22.   border-radius: 3px;
  23.   margin: 10px;
  24. }
  25. </style>
复制代码
BaseB.vue(发送方)
  1. <template>
  2.   <div class="base-b">
  3.     <div>我是B组件(发布方)</div>
  4.     <button>发送消息</button>
  5.   </div>
  6. </template>
  7. <script>
  8. import Bus from '../utils/EventBus'
  9. export default {
  10. }
  11. </script>
  12. <style scoped>
  13. .base-b {
  14.   width: 200px;
  15.   height: 200px;
  16.   border: 3px solid #000;
  17.   border-radius: 3px;
  18.   margin: 10px;
  19. }
  20. </style>
复制代码
App.vue
  1. <template>
  2.   <div class="app">
  3.     <BaseA></BaseA>
  4.     <BaseB></BaseB>
  5.   </div>
  6. </template>
  7. <script>
  8. import BaseA from './components/BaseA.vue'
  9. import BaseB from './components/BaseB.vue'
  10. export default {
  11.   components:{
  12.     BaseA,
  13.     BaseB
  14.   }
  15. }
  16. </script>
  17. <style>
  18. </style>
复制代码
4.总结

1.非父子组件传值借助什么?
2.什么是变乱总线
3.发送方应该调用变乱总线的哪个方法
4.接收方应该调用变乱总线的哪个方法
5.一个组件发送数据,可不可以被多个组件接收
十五、非父子通讯-provide&inject

1.作用

跨层级共享数据
2.场景


3.语法


  • 父组件 provide提供数据
  1. export default {
  2.   provide () {
  3.     return {
  4.        // 普通类型【非响应式】
  5.        color: this.color,
  6.        // 复杂类型【响应式】
  7.        userInfo: this.userInfo,
  8.     }
  9.   }
  10. }
复制代码
2.子/孙组件 inject获取数据
  1. export default {
  2.   inject: ['color','userInfo'],
  3.   created () {
  4.     console.log(this.color, this.userInfo)
  5.   }
  6. }
复制代码
4.注意



  • provide提供的简朴类型的数据不是响应式的,复杂类型数据是响应式。(保举提供复杂类型数据)
  • 子/孙组件通过inject获取的数据,不能在自身组件内修改
十六、v-model原理

1.原理:

v-model本质上是一个语法糖。例如应用在输入框上,就是value属性 和 input变乱 的合写
  1. <template>
  2.   <div id="app" >
  3.     <input v-model="msg" type="text">
  4.     <input :value="msg" @input="msg = $event.target.value" type="text">
  5.   </div>
  6. </template>
复制代码
2.作用:

提供数据的双向绑定


  • 数据变,视图跟着变 :value
  • 视图变,数据跟着变 @input
3.注意

$event 用于在模板中,获取变乱的形参
4.代码示例

  1. <template>
  2.   <div class="app">
  3.     <input type="text"  />
  4.     <br />
  5.     <input type="text" />
  6.   </div>
  7. </template>
  8. <script>
  9. export default {
  10.   data() {
  11.     return {
  12.       msg1: '',
  13.       msg2: '',
  14.     }
  15.   },
  16. }
  17. </script>
  18. <style>
  19. </style>
复制代码
5.v-model使用在其他表单元素上的原理

差别的表单元素, v-model在底层的处理机制是不一样的。比如给checkbox使用v-model
底层处理的是 checked属性和change变乱。
不过咱们只须要掌握应用在文本框上的原理即可
十七、表单类组件封装

1.需求目标

实现子组件和父组件数据的双向绑定 (实现App.vue中的selectId和子组件选中的数据进行双向绑定)
2.代码演示

App.vue
  1. <template>
  2.   <div class="app">
  3.     <BaseSelect></BaseSelect>
  4.   </div>
  5. </template>
  6. <script>
  7. import BaseSelect from './components/BaseSelect.vue'
  8. export default {
  9.   data() {
  10.     return {
  11.       selectId: '102',
  12.     }
  13.   },
  14.   components: {
  15.     BaseSelect,
  16.   },
  17. }
  18. </script>
  19. <style>
  20. </style>
复制代码
BaseSelect.vue
  1. <template>
  2.   <div>
  3.     <select>
  4.       <option value="101">北京</option>
  5.       <option value="102">上海</option>
  6.       <option value="103">武汉</option>
  7.       <option value="104">广州</option>
  8.       <option value="105">深圳</option>
  9.     </select>
  10.   </div>
  11. </template>
  12. <script>
  13. export default {
  14. }
  15. </script>
  16. <style>
  17. </style>
复制代码
十八、v-model简化代码

1.目标:

父组件通过v-model 简化代码,实现子组件和父组件数据 双向绑定
2.如何简化:

v-model其实就是 :value和@input变乱的简写


  • 子组件:props通过value接收数据,变乱触发 input
  • 父组件:v-model直接绑定数据
3.代码示例

子组件
  1. <select :value="value" @change="handleChange">...</select>
  2. props: {
  3.   value: String
  4. },
  5. methods: {
  6.   handleChange (e) {
  7.     this.$emit('input', e.target.value)
  8.   }
  9. }
复制代码
父组件
  1. <BaseSelect v-model="selectId"></BaseSelect>
复制代码
十九、.sync修饰符

1.作用

可以实现 子组件父组件数据双向绑定,简化代码
简朴明白:子组件可以修改父组件传过来的props值
2.场景

封装弹框类的基础组件, visible属性 true体现 false隐蔽
3.本质

.sync修饰符 就是 :属性名@update:属性名 合写
4.语法

父组件
  1. //.sync写法
  2. <BaseDialog :visible.sync="isShow" />
  3. --------------------------------------
  4. //完整写法
  5. <BaseDialog
  6.   :visible="isShow"
  7.   @update:visible="isShow = $event"
  8. />
复制代码
子组件
  1. props: {
  2.   visible: Boolean
  3. },
  4. this.$emit('update:visible', false)
复制代码
5.代码示例

App.vue
  1. <template>
  2.   <div class="app">
  3.     <button @click="openDialog">退出按钮</button>
  4.     <BaseDialog :isShow="isShow"></BaseDialog>
  5.   </div>
  6. </template>
  7. <script>
  8. import BaseDialog from './components/BaseDialog.vue'
  9. export default {
  10.   data() {
  11.     return {
  12.       isShow: false,
  13.     }
  14.   },
  15.   components: {
  16.     BaseDialog,
  17.   },
  18. }
  19. </script>
  20. <style>
  21. </style>
复制代码
BaseDialog.vue
  1. <template>
  2.   <div class="base-dialog-wrap" v-show="isShow">
  3.     <div class="base-dialog">
  4.       <div class="title">
  5.         <h3>温馨提示:</h3>
  6.         <button class="close">x</button>
  7.       </div>
  8.       <div class="content">
  9.         <p>你确认要退出本系统么?</p>
  10.       </div>
  11.       <div class="footer">
  12.         <button>确认</button>
  13.         <button>取消</button>
  14.       </div>
  15.     </div>
  16.   </div>
  17. </template>
  18. <script>
  19. export default {
  20.   props: {
  21.     isShow: Boolean,
  22.   }
  23. }
  24. </script>
  25. <style scoped>
  26. .base-dialog-wrap {
  27.   width: 300px;
  28.   height: 200px;
  29.   box-shadow: 2px 2px 2px 2px #ccc;
  30.   position: fixed;
  31.   left: 50%;
  32.   top: 50%;
  33.   transform: translate(-50%, -50%);
  34.   padding: 0 10px;
  35. }
  36. .base-dialog .title {
  37.   display: flex;
  38.   justify-content: space-between;
  39.   align-items: center;
  40.   border-bottom: 2px solid #000;
  41. }
  42. .base-dialog .content {
  43.   margin-top: 38px;
  44. }
  45. .base-dialog .title .close {
  46.   width: 20px;
  47.   height: 20px;
  48.   cursor: pointer;
  49.   line-height: 10px;
  50. }
  51. .footer {
  52.   display: flex;
  53.   justify-content: flex-end;
  54.   margin-top: 26px;
  55. }
  56. .footer button {
  57.   width: 80px;
  58.   height: 40px;
  59. }
  60. .footer button:nth-child(1) {
  61.   margin-right: 10px;
  62.   cursor: pointer;
  63. }
  64. </style>
复制代码
6.总结

1.父组件如果想让子组件修改传已往的值 必须加什么修饰符?
2.子组件要修改父组件的props值 必须使用什么语法?
二十、ref和$refs

1.作用

使用ref 和 $refs 可以用于 获取 dom 元素 或 组件实例
2.特点:

查找范围 → 当前组件内(更精确稳定)
3.语法

1.给要获取的盒子添加ref属性
  1. <div ref="chartRef">我是渲染图表的容器</div>
复制代码
2.获取时通过 $refs获取 this.$refs.chartRef 获取
  1. mounted () {
  2.   console.log(this.$refs.chartRef)
  3. }
复制代码
4.注意

之前只用document.querySelect(‘.box’) 获取的是整个页面中的盒子
5.代码示例

App.vue
  1. <template>
  2.   <div class="app">
  3.     <BaseChart></BaseChart>
  4.   </div>
  5. </template>
  6. <script>
  7. import BaseChart from './components/BaseChart.vue'
  8. export default {
  9.   components:{
  10.     BaseChart
  11.   }
  12. }
  13. </script>
  14. <style>
  15. </style>
复制代码
BaseChart.vue
  1. <template>
  2.   <div class="base-chart-box" ref="baseChartBox">子组件</div>
  3. </template>
  4. <script>
  5. // yarn add echarts 或者 npm i echarts
  6. import * as echarts from 'echarts'
  7. export default {
  8.   mounted() {
  9.     // 基于准备好的dom,初始化echarts实例
  10.     var myChart = echarts.init(document.querySelect('.base-chart-box'))
  11.     // 绘制图表
  12.     myChart.setOption({
  13.       title: {
  14.         text: 'ECharts 入门示例',
  15.       },
  16.       tooltip: {},
  17.       xAxis: {
  18.         data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
  19.       },
  20.       yAxis: {},
  21.       series: [
  22.         {
  23.           name: '销量',
  24.           type: 'bar',
  25.           data: [5, 20, 36, 10, 10, 20],
  26.         },
  27.       ],
  28.     })
  29.   },
  30. }
  31. </script>
  32. <style scoped>
  33. .base-chart-box {
  34.   width: 400px;
  35.   height: 300px;
  36.   border: 3px solid #000;
  37.   border-radius: 6px;
  38. }
  39. </style>
复制代码
二十一、异步更新 & $nextTick

1.需求

编辑标题, 编辑框自动聚焦

  • 点击编辑,体现编辑框
  • 让编辑框,立刻获取焦点

2.代码实现

  1. <template>
  2.   <div class="app">
  3.     <div v-if="isShowEdit">
  4.       <input type="text" v-model="editValue" ref="inp" />
  5.       <button>确认</button>
  6.     </div>
  7.     <div v-else>
  8.       <span>{{ title }}</span>
  9.       <button @click="editFn">编辑</button>
  10.     </div>
  11.   </div>
  12. </template>
  13. <script>
  14. export default {
  15.   data() {
  16.     return {
  17.       title: '大标题',
  18.       isShowEdit: false,
  19.       editValue: '',
  20.     }
  21.   },
  22.   methods: {
  23.     editFn() {
  24.         // 显示输入框
  25.         this.isShowEdit = true  
  26.         // 获取焦点
  27.         this.$refs.inp.focus()
  28.     }  },
  29. }
  30. </script>
复制代码
3.问题

“体现之后”,立刻获取焦点是不能成功的!
缘故原由:Vue 是异步更新DOM (提升性能)
4.办理方案

$nextTick:等 DOM更新后,才会触发执行此方法里的函数体
语法: this.$nextTick(函数体)
  1. this.$nextTick(() => {
  2.   this.$refs.inp.focus()
  3. })
复制代码
注意:$nextTick 内的函数体 肯定是箭头函数,这样才气让函数内部的this指向Vue实例

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

守听

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表