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(()=>{
// 业务逻辑
})