目录
一、props配置
(1)简单声明接收
props:['name','age','sex']
(2)子组件接收父组件的参数的同时对数据进行类型限制
props:{
name:String,
age:Number,
sex:String
}
(3)接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
props:{
name:{
type:String, //name的类型是字符串
required:true, //name是必要的
},
age:{
type:Number,
default:99 //默认值
}
}
二、全局事件总线
1.作用
在 vue 里我们可以通过全局事件总线来实现任意组件之间通信
2.原理
它的原理是给 Vue 的原型对象上面添加一个属性。这样的话我所有组件的都可以访问到这个属性,然后可以通过这个属性来访问其他组件给这个属性上面绑定的一些方法,从而去传递数据。而且这个属性还可以去访问 Vue 实例对象上的方法。因为 Vue 组件构造函数的原型对象的原型对象是指向 Vue 的原型对象的。全局事件总线并不是插件,配置文件等等,事件总线是程序员在做Vue开发中总结积累的一套方法,是一套规则,只要满足这套规则,就可以实现组件间的通信。
3.使用
以下的写法是针对vue2的写法,对vue3的后续会另外总结
(1)main.js中,增加以下代码
//引入Vue
import Vue from 'vue';
//引入App
import App from './App';
//关闭vue的生产提示
Vue.config.productionTip = false
//创建vm
new Vue({
el: "#app",
render: h => h(App),
//这个是关键
beforeCreate() {
Vue.prototype.$bus = this//安装全局事件总线
}
})
(2)School.vue 中给 $bus 绑定 hello 事件
<template>
<div class="school">
<h2>学校名称:{
{ name }}</h2>
<h2>学校地址:{
{ address }}</h2>
</div>
</template>
<script>
export default {
name: "School",
data() {
return {
name: "三里屯小学",
address: "北京"
}
},
mounted() {
//给$bus绑定hello事件
this.$bus.$on("hello", (data) => {
console.log("我是school组件,接收到了数据:" + data);
})
},
beforeDestroy() {
this.$bus.off("hello")
}
}
</script>
<style scoped>
</style>
总结:mounted(){
// 绑定自定义事件
this.$bus.$on('自定义事件名', (接收参数)=>{
console.log('我是组件,收到了数据', 接收参数);
})
}
(3)Student.vue 中触发事件
<template>
<div class="student">
<h2>学生姓名:{
{ name }}</h2>
<h2>学生年龄:{
{ age }}</h2>
<button @click="sendStudentName">点我向School组件传递学生姓名</button>
</div>
</template>
<script>
export default {
name: "Student",
data() {
return {
name: "张三",
age: 18
}
},
methods:{
sendStudentName(){
//这个是关键,发送事件
this.$bus.$emit("hello",this.name)
}
}
}
</script>
<style scoped>
</style>
总结: methods:{
// 触发事件,事件名不能重复
触发事件方法名(){
this.$bus.$emit('自定义事件名', 传递参数);
}
}
三、插槽
1.默认插槽
如果我们只在使用组件时的组件标签体内写上内容,那页面上是显示不出来任何东西的,这是因为标签体内的内容确实被解析了,但是vue不知道要把这些东西放在组件中 template 的哪个位置,故我们要在组件的 template 中设置一个插槽来占位,以保证使用组件时其解析的内容可以放入占的位置中去。占位我们使用一个很重要的标签 ------ slot,我们需要在组件的 template 中这样书写:
<template>
<div>
<span>我是一个组件,下面是我的插槽内容</span>
<slot></slot> //默认插槽
</div>
</template>
定义一个插槽<slot></slot>
这样使用组件时组件标签体中的内容就可以放入组件的默认插槽中了
2.具名插槽
具名插槽其实只是在默认插槽的基础上给每个插槽起了名字,作用为可以在组件中设置多个插槽,可以更具体细分。首先给组件插槽起名字,使用 name="xxx"。
定义一个具名插槽<slot name="center">
3.作用域插槽
作用域插槽就是带有数据的插槽,把组件中的数据绑定给插槽,然后谁使用这个组件谁就能拿到这个数据使用,也相当于一种数据通信,其需要这样把数据绑定定义给组件插槽(名称没有要求)
插槽带数据或方法:<slot :games="games" msg="hello">我是默认的一些内容</slot>
这个里面的games就是将数据绑定给组件插槽,在需要用到这个组件的地方可以接收到这个参数
<template scope="{games}"></template>
四、Vuex
1.vuex是什么
- vuex的作用是解决多组件状态共享的问题,在大型的项目中,组件通讯会变得很混乱,使用vuex可以统一管理组件之间的通讯
- vuex是响应式布局: 只要vuex中的数据变化,对应的组件会自动更新(类似于vue数据驱动)
vuex 是一个状态管理工具,主要解决大中型复杂项目的 数据共享问题,主要包括 state,mutations,actions,getters 和 modules 5 个要 素,主要流程:在页面通过 调用dispatch触发actions执行异步操作,在vue2中,不需要引入useStore,可以直接this.$store.dispatch,vue3最大的特点是按需引入,用到那个api就要引入那个, actions里有默认参数context,在actions通过context.commit(‘给mutations的事件’,‘给mutations的值’)调用mutations,在mutations中的默认参数是state, mutations是唯一修改state的地方
2.vuex工作流程
我们先触发了Actions中的异步操作,当异步结果出来之后(如果没有异步操作则直接执行后面的操作),我们触发commit调用mutations去修改我们的state,最后因为我们是具有响应式的特点,因此我们的数据被修改成功。
3.vuex的API
(1)state
state提供vuex唯一的公共数据源,所有共享的数据都要统一放到store中的State中存储。
state:{
//在此处写共享属性即可
}
//准备state——用于存储数据
const state = {
sum:0 //当前的和
}
(2)state辅助函数mapState
将vuex中的数据映射到组件的计算属性中,简化书写操作(写在computed中)
1.导入import { mapState } from 'vuex'
2. ...mapState([‘state中属性名’])
借助mapState生成计算属性,从state中读取数据。(对象写法)
...mapState({he:'sum',xuexiao:'school',xueke:'subject'})
借助mapState生成计算属性,从state中读取数据。(数组写法)
...mapState(['sum','school','subject'])
(3)mutations
state数据的修改只能通过mutations,并且mutations必须是同步的。Mutations是同步更新state数据的唯一方式!!!
mutations:{
第一个参数是必须的,表示当前的state。
第二个参数是可选的,表示载荷,是可选的。在使用时要传入的数据
专业术语载荷:表示额外的参数
mutation名(state , 载荷 ) {
},
mutations:{
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
当我们点击按钮的时候,我们荷载(value)中的数据传到了mutation中随后完成我们的值传递,将我们原始的数据改变。
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
(4)mutations辅助函数mapMutations
简化书写操作成方法形式(写在methods中)
1.导入import { mapMutations } from 'vuex'
2. ...mapMutations([‘mutations名’])
借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
//第一个为本地方法名,第二个参数为中的方法名
...mapMutations({increment:'JIA',decrement:'JIAN'})
借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
//当本地和index.js中的方法名一致时,可以简化成数组写法
...mapMutations(['JIA','JIAN'])
(5)actions
actions: 异步更新我们的数据(例如你的数据来源于ajax)
actions: {
// context对象会自动传入,它与store实例具有相同的方法和属性
action的名字(context, 载荷) {
// 1. 异步操作获取数据
// 2. commit调用mutation来修改数据
// context.commit('mutation名', 载荷)
}
}
第一个参数是必须的,表示当前的state。
第二个参数是可选的,表示载荷,是可选的。在使用时要传入的数据
专业术语载荷:表示额外的参数
this.$store.dispath ( 'actions的名字',参数)
(6)actions辅助函数mapActions
简化书写操作成方法形式(写在methods中)
1.导入import { mapActions } from 'vuex'
2. ...mapmapActions([‘action名’])
借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
//第一个为本地方法名,第二个参数为actions中的方法名
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
//当本地和index.js中的方法名一致时,可以简化成数组写法
...mapActions(['jiaOdd','jiaWait'])
(7)getters
getters: {
计算属性名()(state) {
return 要返回的值
}
}
$store.getters.getter名
(8)getters辅助函数mapGetters
同上是简化我们的写法(写在computed中)
1.导入import { mapGetters } from 'vuex'
2. ...mapGetters([‘getters中计算属性’]
借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
...mapGetters({bigSum:'bigSum'})
借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters(['bigSum'])
(9)modules
模块化处理vuex数据,将我们每个模块的vuex数据分开处理
//在我们的store/index.js中书写
modules: {
模块名1: {
// namespaced为true,则在使用mutations时,就必须要加上模块名
namespaced: true,
}
}
export default导出对应的模块
在每个模块必须写上namespaced:true
导入模块名
在modules中使用模块
(10)总结
//state
全局的: $store.state.数据项名
模块的: $store.state.模块名.数据项名
//getters
全局的: $store.getters.getter名
模块的: $store.getters['模块名/getters名']
//mutations
全局的: $store.commit('mutations名',载荷)
模块的: $store.commit('模块名/mutations名',载荷)
//actions
全局的: $store.dispatch('actions名',载荷)
模块的: $store.dispatch('模块名/actions名',载荷)