前言: 紧跟前文,目标学习Vue2.0——3.0: 懂个锤子Vue、WebPack5.0、WebPack高级进阶 涉及的技术栈…
当然既然学习框架的了,HTML+CSS+JS三件套必须的就不说了: JavaScript 快速入门
学习前置链接: 懂个锤子Vue 项目工程化
在 Vue 开发中,组件样式冲突是一个常见的问题: 为什么会发生组件样式冲突⁉️
我们都知道,组件是由:模板Template\脚本Script\样式Style
组成,每个组件都是有自己的三件套)
但,因为Vue在运行过程中,本质是将多个组件合并成一个:html文件
所以,多个组件样式,相互匹配就发生组件样式冲突:
Vue支持定义全局\局部样式:
默认情况: 组件中的样式会,全局生效
→ 很容易造成多个组件之间的样式冲突问题,
默认
组件中的样式会作用到全局scoped可以让组件样式变成局部样式: 组件都应该有独立的样式
scoped:
给当前组件模板的所有元素,都会添加上一个自定义属性data-v-hash值
data-v-hash值:
用于区分开不通的组件,渲染样式时css选择器
后面,被自动处理,添加上了属性选择器;在 Vue 组件中,**data
** 函数的主要作用是为每个组件实例提供独立的数据对象:
date(函数){ return {} }
return
返回对象,确保每一个组件都是独立的数据源;访问组件实例: 在 data(){ //函数内部 }
你可以访问组件实例的其他属性和方法;
响应式系统: Vue响应式系统,会将 data 函数
返回的对象包裹起来,
并以 $data
的形式存储在组件实例;数据发生变化,自动更新视图;
<!-- 模板结构 -->
<template>
<div>
<P>A组件: 声明成功!</P>
<button @click="count--">-</button>
<span>{{ count }}</span>
<button @click="count++">+</button>
</div>
</template>
<!-- 脚本结构 -->
<script>
export default {
//原始定义:组件不支持\报错x)
// data: {
// //基本数据类型使用
// count:1
// },
//组件函数式定义:
data(){
//因为: 一个组件可能会使用多次,如果通过原始属性,多个组件会依赖一个数据源;
//通过: date(函数){ return {} } return返回对象,确保每一个组件都是独立的数据源;
return {
count:1
}
}
}
</script>
<!-- 样式结构 -->
<!-- style中的样式,默认是作用到全局的
scoped可以让样式变成局部样式,组件都应该有独立的样式,推荐scoped 原理)
scoped给当前组件模板的所有元素,都会添加上一个自定义属性
data-v-hash值 用于区分开不通的组件,css选择器后面,被自动处理,添加上了属性选择器;
-->
<style scoped>
div{
border: 3px solid red;
margin: 30px;
}
</style>
Vue.js 是一个基于组件的框架,应用通常由多个组件组成:
组件通信是指在 Vue.js 应用中,不同组件之间传递数据和消息的过程:
组件之间的数据是独立的,无法直接访问其他组件的数据,组件通信的主要目的是:
组件之间有哪些关系?
例如,组件A
包含组件B
+组件C
,那么 A 和 B、C 是父子关系;
兄弟\隔代
关系,同一个父组件下的多个子组件之间的关系; 组件B
和 组件C
都是组件A
的子组件,那么 B 和 C 是兄弟关系;
组件A
包含组件B
,组件B
又包含组件D
,那么 A 和 D 是隔代关系;
对应的组件通信方案有哪几类? 这里简单介绍,常用的几种;
Props
是父组件向子组件传递数据的机制,
父组件通过在子组件标签上绑定属性来传递数据,子组件通过声明 props
来接收这些数据;
<组件名 :属性名='传递值' ></组件名>
props
获取父组件的数据,props:['属性名']
,props
中的属性可以像data
中数据一样使用;Props
作用: 向子组件传递数据,可以传递任意数量
、可以传递任意类型
props
校验是确保传递给组件的数据符合预期的一种机制: 通过定义 props
的类型和验证规则,提高组件可靠性和可维护性;
'props': {
'校验属性名1': '类型', // Number String Boolean ...
'校验属性名2': {
type: '类型', // Number String Boolean ...
required: true, // 是否必填
default: '默认值', // 默认值
validator (value) {
// 自定义校验逻辑
return 是否通过校验;
};
}
},
在 Vue.js 中,**props
** 和 data
都是用于管理组件数据的重要机制,但它们有一些显著的区别:
data
:用于组件内部管理数据,组件可以自由修改props
:用于父组件向子组件传递数据,子组件只能读取,不能修改单向数据流: 父级 props 的数据更新,会向下流动,影响子组件,这个数据流动是单向的
父组件更新 props
,子组件会接收到最新的数据,但子组件不能直接修改 props
的值,子组件修改值**报错
**⚡
检测到props
中数据修改报错,Vue直接抛出异常! 那么如何修改父组件的数据呢?
👆这就涉及到子——父
通信了,那么如何: 子—>父通信:
BaseCount.vue: 子组件通过调用 $emit
方法触发一个@自定义事件
,
并传递需要发送的数据:this.$emit('自定义事件名', 传递给父组件数据)
<!-- 模板结构 -->
<template>
<div class="base-count">
<button @click="handleSub">-</button>
<span>{{ count }}</span>
<button @click="handleAdd">+</button>
</div>
</template>
<!-- 脚本结构 -->
<script>
export default {
//子组件data数据
data(){ return { dcount:0 } },
props: {
//props获取父组件数据;
count: { type: Number, },
},
methods: {
handleSub() {
//子组件通过调用 $emit 方法触发一个自定义事件,并传递需要发送的数据
this.$emit('changeCount', this.count - 1)
},
handleAdd() {
this.$emit('changeCount', this.count + 1)
},
},
}
</script>
<!-- 样式结构 -->
<style></style>
App.vue: 父组件通过在:子组件标签上自定义监听事件
,并绑定一个函数来接收处理数据;
<子组件 :属性名='传递值' @自定义监听事件="处理函数" >
,当子组件调用:this.$emit('自定义事件名', 传递父组件数据)
父组件监听事件触发,并执行对应处理函数,函数内部可以获取子组件传递的数据: 处理函数(value){ //内部执行相应处理 }
<!-- 模板结构 -->
<template>
<div id="app" style="border: 3px solid #000; margin: 10px">
App 父组件
<!-- 加减组件 -->
<!-- 父组件通过在子组件标签上监听自定义事件,并绑定一个触发函数 -->
<BaseCount :count="count" @changeCount="handleChange" ></BaseCount>
</div>
</template>
<!-- 脚本结构 -->
<script>
import BaseCount from './components/BaseCount.vue'
export default {
name: 'App',
data(){
return { count:1, }
},
components: {
BaseCount
},
methods:{
handleChange(newVal){
//函数获取: 子组件传递的数据,给其赋值count;
this.count = newVal;
}
}
}
</script>
<!-- 样式结构 -->
<style></style>
+\-
触发对应的子组件函数,this.$emit('父组件自定义监听函数',传递值)
给父组件传递修改后的值;@自定义函数
**执行,并触发函数count
在 Vue.js 中,事件总线(Event Bus)是一种用于实现非父子组件之间通信的机制
它允许我们在 Vue 应用中 创建一个全局的事件中心 ,组件通过该 事件中心
**来:发送\接收事件** ,实现数据的传递和共享
首先,我们需要创建一个事件总线:
main.js
,中创建一个新的 Vue 实例,并将其挂载到 Vue 的原型上,以便所有组件都可以访问;//全局工具包
//utils/EventBus.js
import Vue from 'vue';
const EventBus = new Vue();
export default EventBus; //对外暴漏公共实例;
//main.js
//const EventBus = new Vue();
//Vue.prototype.$bus = EventBus;
//将一个新的 Vue 实例即EventBus)挂载到Vue的原型上,并命名为 $bus
//这样,所有的 Vue 组件都可以通过 this.$bus 访问这个事件总线;
在需要发送事件的组件中,通过 实例.$emit
方法发送事件,并传递数据;
<template>
<div class="base-b">
<div>我是B组件(发布方)</div>
<button @click="sendMsgFn">发送消息1</button>
<button @click="sendMsgFn2">发送消息2</button>
</div>
</template>
<script>
//引入局部事件总线
import Bus from '../utils/EventBus'
export default {
methods: {
//通过 `$bus.$emit` 方法发送事件,并传递数据;
sendMsgFn() { Bus.$emit('sendMsg', '引入局部事件总线') },
sendMsgFn2() { this.$bus.$emit('sendMsg2', 'this.$Bus全局事件总线') },
},
}
</script>
<style scoped><!-- 省略Css样式 --></style>
在需要接收事件的组件中,通过 $bus.$on
方法监听事件,并处理接收到的数据;
<template>
<div class="base-a">
我是A组件(接受方)
<p>{{msg}}</p>
</div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
data() { return { msg: '', } },
created() {
Bus.$on('sendMsg', (msg) => { this.msg = msg }); //接受局部事件总线消息
this.$bus.$on('sendMsg2', (msg) => { this.msg = msg }); //接受全局事件总线消息
},
}
</script>
<style scoped><!-- 省略Css样式 --></style>
事件移除:在组件销毁前,应该移除事件监听,以避免内存泄漏和重复监听,
全局事件总线: 虽然事件总线使用方便,但在大型应用中可能会导致难以维护的“灾难”,
因此需要谨慎使用,对于复杂的状态管理,推荐使用 Vuex:
在 Vue.js 中,**provide
** 和 inject
是一种高级的数据传递机制:
主要用于解决组件树中深层组件间通信的问题,特别是当不直接存在父子关系时
它们允许父组件提供一个值,而任何后代组件都可以通过 inject
来接收这个值;如:上图D—A的隔代通信;
父组件使用 provide 提供数据: 父组件通过 provide(){ return { 发送数据 } }
选项将数据提供给子组件及其后代组件;
<template>
<div id="app" style="border: 3px solid #000; margin: 10px">
App 父组件
<Son3></Son3>
</div>
</template>
<script>
import Son3 from './components/Son3.vue';
export default {
name: 'App',
components: { Son3, },
data() { return { color: 'pink', userInfo: { name: 'zs', age: 18, }, } },
//父组件使用 provide 提供数据:
provide() {
return {
// 简单类型是非响应式的
color: this.color,
// 复杂类型 是响应式的
userInfo: this.userInfo,
}
},
}
</script>
子组件使用 inject 接收数据: 子组件通过 inject: ['匹配数据名', '匹配数据名','...']
选项注入这些数据;
<template>
<div class="grandSon">
我是GrandSon
{{ color }} -{{ userInfo.name }} -{{ userInfo.age }}
</div>
</template>
<script>
export default {
//子组件使用 inject 接收数据:
inject: ['color', 'userInfo'],
}
</script>
需要注意的是,provide
提供的简单类型数据(如字符串、数字)是非响应式的,
而复杂类型数据(如对象、数组)是响应式的,这意味着子组件可以监听到复杂类型数据的变化;
本代码已经使用Git进行管理: 公众号回复:Vue项目工程化
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。