学习vue第四天

89 阅读2分钟

Day4:

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

1.组件的样式冲突 scoped
    1.默认情况:写在组件中的样式会 全局生效→ 因此很容易造成多个组件之间的样式冲突问题。
        1.全局样式:默认组件中的样式会作用到全局
        2.局部样式:可以给组件加上 scoped 属性,可以让样式只作用于当前组件
    2.scoped原理?
        1.当前组件内标签都被添加 data-v-hash值 的属性
        2.css选择器都被添加[data-v-hash值]的属性选择器
        最终效果:必须是当前组件的元素,才会有这个自定义属性,才会被这个样式作用到
2.data是一个函数
    一个组件的 data 选项必须是一个函数。→ 保证每个组件实例,维护独立的一份数据对象。每次创建新的组件实例,都会新执行一次 data 函数,得到一个新对象。

2.组件通信

1.什么是组件通信?
    组件通信,就是指 组件与组件 之间的数据传递。
    1.组件的数据是独立的,无法直接访问其他组件的数据,
    2.想用其他组件的数据 →组件通信
2.组件关系分类:
    1.父子关系
    2.非父子关系
3.组件通信解决方案:
    1.父子关系
        props 和 $emit
    2.非父子关系
        1. provide & inject
        2.eventbus
    3.通用解决方案:Vuex(适合复杂业务场景)
4.父子通信流程图
    1.父组件通过 props 将数据传递给子组件
    2.子组件利用 $emit 通知父组件修改更新
5.小结
    1.两种组件关系分类 和 对应的组件通信方案
        1.父子关系    ->   props &$emit
        2.非父子关系(拓展)  ->  provide &inject 或eventbus-’
        3.通用方案    ->  vuex
    2.父子通信方案的核心流程
        1.父传子props:
            1.父中给子添加属性传值    2.子props 接收    3.使用
        2.子传父$emit:
            1.子$emit 发送消息    2.父中给子添加消息监听    3.父中实现处理函数
6.什么是 prop?
    1.Prop 定义:组件上 注册的一些 自定义属性
    2.Prop 作用:向子组件传递数据
    3.特点:1.可以 传递 任意数量 的prop
            2.可以 传递 任意类型 的prop
    4.思考:组件的 prop 可以乱传么?  不可以
    5.作用:为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示   →   帮助开发者,快速发现错误
    6.检验方法类型:
        1.类型校验
        2.非空校验
        3.默认值
        4.自定义校验
        5.语法:
          1.类型检验语法:
              props: {
              校验的属性名:类型      //Number string Boolean ...
              }
          2.完整检验语法:
              props:{
                校验的属性名:{
                  type: 类型,                 //Number string Boolean ...
                  required: true,             // 是否必填
                  default:  默认值,           //默认值
                  validator(value){           // 自定义校验逻辑
                    return 是否通过校验
                  }
                }
              },
7.非父子通信(拓展)
  1.event bus 事件总线
    作用:非父子组件之间,进行简易消息传递。(复杂场景  → Vuex)
      1.创建一个都能访问到的事件总线(空 Vue 实例) → utils/EventBus.js
          import Vue from 'vue'
          const Bus = new Vue()
          export default Bus
      2.A 组件(接收方),监听 Bus 实例 的事件
          created(){
            Bus.$on('sendMsg',  (msg)=> {
              this.msg = msg
            })
          }
      3.B 组件(发送方),触发 Bus 实例的事件
          Bus.$emit('sendMsg','这是一个消息')
      4.可以一对多  再来一个c组件接收方  一样也是可以的
2.provide & inject
    作用:跨层级共享数据。孙组件也可以共享到数据
      1.父组件 provide 提供数据
          export default {
            provide(){
              return {
                color:this.color,           // 普通类型【非响应式】
                userInfo: this.userInfo,    //复杂类型【响应式】
              }
            }
          }
      2.子/孙组件 inject 取值使用
          export default{
            inject:['color','userInfo'],
            created(){
              console.log(this.color,this.userInfo)
            }
          }

3.综合案例:小黑记事本(组件版)

拆分组件/渲染/添加/删除/统计/清空/持久化
    第52-54集

4.进阶语法

1.v-model原理
    1.原理:v-model本质上是一个语法糖。例如应用在输入框上,就是 value属性 和 input事件 的合写。
    2.作用:提供数据的双向绑定
        1.:value:数据发生改变,页面会自动变
        2.@input:页面输入改变,数据会自动变 
      注意:$event用于在模板中,获取事件的形参
    3.语法示例:
        <template>
          <div id="app" >
            <input v-model="msg" type="text">
            <input :value="msg" @input="msg = $event.target.value" type="text">
          </div>
        </template>
2.表单类组件封装&v-model 简化代码
    1.表单类组件 封装 -> 实现 子组件 和 父组件数据 双向绑定
        1.父传子:数据 应该是父组件 props 传递过来的,v-model 拆解 绑定数据
        2.子传父:监听输入,子传父传值给父组件修改
        3.语法:
            1.父组件(使 用):  <BaseSelect :cityId="selectId" @事件名="selecteId = $event" />
            2.子组件(封 装):  <select :value="cityId" @change="handlechange">...</select>
                              props:{
                                cityId: string
                              },
                              methods:{
                                handlechange(e){
                                  this.$emit('事件名',  e.target.value)
                                }
                              }
    2.父组件 v-model简化代码,实现 子组件 和 父组件数据 双向绑定
        1.子组件中:props 通过 value 接收,事件触发 input
        2.父组件中:v-model给组件直接绑数据  (:value+@input)
        3.语法:
            1.父组件(使 用):<BaseSelect v-model="selectId"></BaseSelect>
                            //<BaseSelect :value="selectId" @input="selecteId = $event"/>
            2.子组件(封 装):<select :value="value" @change="handlechange">...</select>
                              props:{
                                value: string
                              },
                              methods:{
                                handleChange(e){
                                  this.$emit('input', e.target.value)
                                }
                              }
3.总结                              
    1.表单类基础组件封装思路
        1.父传子:父组件动态传递 prop 数据,拆解v-model,绑定数据
        2.子传父:监听输入,子传父传值给父组件修改
          本质:实现了实现 子组件 和 父组件数据 的双向绑定
    2.v-model简化代码的核心步骤
        1.子组件中:props 通过 value 接收,事件触发 input
        2.父组件中:v-model给组件直接绑数据
    3.小作业:封装输入框组件,利用v-model简化代码
4.sync修饰符
    1.作用:可以实现 子组件 与 父组件数据 的 双向绑定,简化代码
    2.特点:prop属性名,可以自定义,并非固定为 value
    3.场景:封装弹框类的基础组件,visible属性 true显示 false隐藏
    4.本质:就是 :属性名 和 @update:属性名 合写
    5.语法:
        1.父组件(使 用)<BaseDialog :visible.sync="isShow"></BaseDialog>
                      //<BaseDialog:visible="isShow"@update:visible="isShow = $event"></BaseDialog>
        2.子组件(封 装):props:{
                          visible: Boolean
                        },
                      this.$emit('update:visible', false)
5.ref和$refs
    1.作用:利用 ref 和 $refs 可以用于 获取 dom 元素, 或 组件实例
    2.特点:查找范围 → 当前组件内(更精确稳定)
    3.获取 dom:
        1.目标标签 - 添加 ref 属性
            <div ref="chartRef">我是渲染图表的容器</div>
        2.恰当时机,通过 this.$refs.xxx,获取目标标签
            mounted()
              console.log(this.$refs.chartRef)
            },
        3.补充://基于准备好的dom,初始化echarts实例
        const mychart = echarts.init(document.querySelector('.box'));         //querySelector 查找范围 → 整个页面  会前面的1.和2.会更方便
    4.获取组件:
        1.目标组件-添加 ref 属性
            <BaseForm ref="baseForm"></BaseForm>
        2.恰当时机,通过 this.$refs.xxx,获取目标组件,就可以调用组件对象里面的方法
            this.$refs.baseForm.组件方法()
6.Vue异步更新、$nextTick
    1.需求:编辑标题,编辑框自动聚焦
        1.点击编辑,显示编辑框
        2.让编辑框,立刻获取焦点
    2.语法:this.isShowEdit = true    //显示输入框
            this.$refs.inp.focus()    //获取焦点
        1.问题:"显示之后",立刻获取焦点是不能成功的!
        2.原因:Vue 是 异步更新 DOM(提升性能)
    3.总结
        1.Vue是异步更新 DOM 的
        2.想要在 DOM 更新完成之后做某件事,可以使用$nextTick
              this.$nextTick(()=>{
                  // 业务逻辑
              })