组件是vue.js中最重要的一个功能,在vue中组件的实例都是相互独立的,但开发过程中组件雨组件之间的数据相互引用是必不可少,下面来阐述vue的几种通信方式
1:父组件->子组件:通过props接受父传递数据
步骤1:子通过props键来接受父传递过来的数据 props:[‘变量名1’,…,‘变量名n’]
步骤2:父传递给子 父必须在调用子的组件上通过语法 v-bind:子props中的变量名=“父data中的键”
// 声明fathertag组件
Vue.component("fathertag", {
// 声明模型数据
data() {
return {
// 调用的时候注意大小写
sonName: "赵冠希"
}
},
// 声明组件内容
template: `
<fieldset>
<legend>父组件</legend>
<div>
<p>我是父组件,我儿子叫:{{sonName}}</p>
<!-- 调用子组件 -->
<sontag v-bind:myName="sonName"></sontag>
</div>
</fieldset>
`,
// 声明子组件
components: {
// 键就是组件标识
sontag: {
// 通过props键来获取父传递的数据
props: ['myName'],
// 这里的下props相当于下面data
// data() {
// return {
// // myName: 数据
// myName: 6666,
// }
// },
// 声明子组件内容
template: `
<fieldset>
<legend>子组件</legend>
<p>我是子组件,我爸爸给我取名:{{myName}}</p>
</fieldset>
`
}
}
})
2:子组件->父组件:通过$emit创建自定义事件发送数据
步骤1:子创建自定义事件 通过语法this.$emit(事件名称, 数据1, …, 数据n)
步骤2:父调用自定义事件 父在调用子组件上通过 @自定义事件名称=“函数名” 你在父定义函数接受数据即可
// 声明fathertag组件
Vue.component("fathertag", {
// 声明模型数据
data() {
return {
// 调用的时候注意大小写
sonName: "赵冠希",
mySonData: ""
}
},
// 声明组件内容
template: `
<fieldset>
<legend>父组件</legend>
<div>
<p>我是父组件,我儿子叫:{{sonName}}</p>
<!-- 调用子组件 -->
<sontag @getSonData="showSonDataFn" v-bind:myName="sonName"></sontag>
<p>
子的数据: {{ mySonData }}
</p>
</div>
</fieldset>
`,
// 声明父普通函数
methods: {
showSonDataFn(data) {
// console.log(data)
this.mySonData = data
}
},
// 声明子组件
components: {
// 键就是组件标识
sontag: {
// 简单理解:页面加载完毕 -> 组件渲染完毕会触发下面这个键
mounted() {
// 在这里面创建自定义事件
this.$emit("getSonData", this.myName2)
},
// 通过props键来获取父传递的数据
props: ['myName'],
// 脚下留心:下props相当于下面data
data() {
return {
// myName: 数据
// myName: 6666,
myName2: "xxxxxx"
}
},
// 声明子组件内容
template: `
<fieldset>
<legend>子组件</legend>
<p>我是子组件,我爸爸给我取名:{{myName}}</p>
</fieldset>
`
}
}
})
3:兄弟组件:通过EventBus(事件总线)
步骤1:创建所有组件共享数据中心 const eventBus = new Vue()
步骤2:传递数据 eventBus.
on(自定义事件名称,处理函数)
// 创建一个组件数据共享中心
const eventBus = new Vue()
Vue.component("mytag1", {
// 声明组件模型数据
data() {
return {
msg: "webopenfather",
other: 66666
}
},
// 声明组件内容
template: `
<fieldset>
<legend>兄弟1</legend>
<button @click="sendDataFn">点击传递数据</button>
</fieldset>
`,
// 声明普通方法
methods:{
sendDataFn() {
// 发送数据
eventBus.$emit("mytag1MsgData", this.msg, this.other)
}
}
})
Vue.component("mytag2", {
// 声明组件内容
template: `
<fieldset>
<legend>兄弟2</legend>
<p>{{data}}</p>
<p>{{data2}}</p>
</fieldset>
`,
// 声明自己的模型数据
data() {
return {
data: "",
data2: ""
}
},
// 组件渲染完毕触发函数
mounted() {
eventBus.$on("mytag1MsgData", (data, data2, data3) => {// 推荐写箭头函数
console.log(data)
console.log(data2)
console.log(data3)
// 将数据保存到自己的模型里面 -> 展示
this.data = data
this.data2 = data2
})
}
})
4:状态管理vuex
在实战中组件之间通信麻烦(两三个兄弟无所谓,但是n个兄弟 比较复杂),所以Vuex实现组件数据统一管理
const store = new Vuex.Store({
// 声明仓库数据
state: {
// 跟其他组件定义data一样
键:值,//
...
},
// 仓库数据过滤
getters: {
方法名(state) {
+return
},
...
},
// 更新仓库数据(这里面不允许写异步请求)
mutations: {
// 无参数
get/set方法名(state) {
},
// 有参数(思考:有几个形参,根据actions调用传递的实参定)
get/set方法名(state, data1, ..., datan) {
state.键 = 异步请求数据(data1)
}
},
// 更新仓库数据(这里面专门写异步请求,但是不能直接操作state 操作mutations)
actions: {
get/set方法名(context) {
//不传递参数:context.commit(mutations里面的方法名)
//传递参数: context.commit(mutations里面的方法名, 数据1,..,数据n)
}
}
})
//
//在组件中触发仓库里面数据语法
//如果在组件中调用state&getter:
computed: {
方法名() { // 推荐方法名就是vuex.state中的键名
return this.$store.state/getters.键
}
}
// 如何调用mutations
// 如何调用actions
methods: {
方法名() {
this.$store.commit(mutations里面方法名)
this.$store.dispatch(actions里面的方法名)
}
}
辅助函数
辅助函数(state):在组件computed里面写 …Vuex.mapState([键1,…,键n])
辅助函数(getters):在组件computed里面写 …Vuex.mapGetters([方法名1,…,方法名n])
辅助函数(mutations)在组件methods等其他 …Vuex.mapMutations([]或者{})
辅助函数(actions) 在组件methods等其他 …Vuex.mapActions([]或{}})
[‘mutations/action方法名里面方法名’] 注:这时候普通方法名 同 数组里面的值
{ 键就是普通方法名,值mutations/action方法名里面方法名 键:值 }
const store = new Vuex.Store({
// 声明仓库数据
state: { // 计算属性 this.$store.state.键
age: 19,
name: 'jack'
},
// 声明过滤的仓库数据
getters: { // 计算属性 this.$store.getters.方法名
username(state) {
return 'hello2' + state.name
}
},
// 声明更新仓库数据键
mutations: { // commit
setAge(state) {
state.age++
}
},
// 声明更新仓库数据(异步请求 -> mutations)
actions: { // dispatch
setAge(context) {
context.commit('setAge')
}
}
})
// this.$store/$el/$data
let vm = new Vue({
// 激活
store,
el: '#app',
data: {
},
computed: {
// 推荐方法名就是vuex.state中的键
// age() {
// return this.$store.state.age
// },
// name() {
// return this.$store.state.name
// },
// username() {
// return this.$store.getters.username
// }
...Vuex.mapState(['age', 'name']),
...Vuex.mapGetters(['username'])
},
methods: {
// testMutation() {
// this.$store.commit('setAge')
// },
// 下述数组里面的值 就是 vuex.mutations里面的方法名
// 默认普通方法名就是 vuex.mutations里面的方法名
// ...Vuex.mapMutations(['setAge']),
...Vuex.mapMutations({
//前面普通方法名,后面是vuex.mutations里面的方法名
testMutation: 'setAge'
}),
// testAction() {
// this.$store.dispatch('setAge')
// }
...Vuex.mapActions({
testAction: 'setAge'
})
}
})
模块化思想
store 在new vue中激活
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
// 公共的
state
getters
mutations
actions
// 单个模块的
modules: {
a: moduleA,
b: moduleB
}
})
//调用组件中获取数据
// 它们都是在computed
...mapState({
方法名: state => state.状态,
方法名: state => state.moduleA.状态,
方法名: state => state.moduleB.状态
}),
...mapGetters({
方法名: '方法名',
方法名: 'moduleA/方法名',
方法名: 'moduleB/方法名'
})
// 它们都是在methods
...mapMutations({
方法名: 'moduleA/方法名',
方法名: 'moduleB/方法名'
}),
...mapActions({
方法名: 'moduleA/方法名',
方法名: 'moduleB/方法名',
})