我们知道父子组件直接的数据传递通过标签属性行间 将数据挂在到了标签上
子组件中通过props特性验证来获取来自父组件的数据 进行渲染
在非父子组件中也借用这样的原理 原理图如下
第一种 子传父 父传子
特点 : 传值要经过父组件 不断寻找各组件之间的从属关系 操作复杂 适合一层 父子兄弟组件传递
代码如下:
//子组件1传值到父组件
<template>
<div>
<!-- 第一种方法属性传递-->
<input type="text" v-model="val" @change="add">请输入
</div>
</template>
<script>
export default {
data() {
return {
val: ""
}
},
methods: {
add() {
//第一中方法
this.$emit('test',this.val);
你在这里触发那个事件 在需要的页面就监听谁
this.val = "";
}
},
}
</script>
//父组件
<template>
<div>
<!-- 父组件-->
<add-student @test="test"></add-student>
<student-list :list="list"></student-list>
</div>
</template>
<script>
import addStudent from '@/components/learn/addStudent.vue';
import studentList from '@/components/learn/studentList';
export default {
data() {
return {
list:[]
}
},
methods: {
test(name) {
this.list.push(name);
console.log(this.list)
}
},
components:{
addStudent,
studentList
}
}
</script>
<style scoped>
</style>
//子组件2接受数据
<template>
<div>
<span>你的数据</span>
<ul>
<li v-for="(item,index) in list">
{{list[index]}}
</li>
</ul>
</div>
</template>
<script>
export default {
//属性传值需要props
props: {
list: {
type: Array,
},
},
第二种事件总线
data() {
return {
list: []
}
}
}
</script>
<style scoped>
</style>
事件总线 在整个vue对象的原型上添加一个新的vue实例(对象)该对象为所有vue组件所有
特点: 当每个组件获取数据时 需要在生命周期函数create()函数中注册来自原型上的自定义事件,当组件多时 需要监听的事件太多 适合少量的组件使用(不同层之间也可以)
代码如下
//main.js
Vue.prototype.state = new Vue();
//实例对象原型上添加新的vue对象 为所有vue组件共有 兄弟子组件可以直接使用 不用经过父组件
子组件1
<template>
<div>
<!-- 第二种事件总线-->
<input type="text" v-model="val" @change="add">请输入
</div>
</template>
<script>
export default {
data() {
return {
val: ""
}
},
methods: {
add() {
//你在这里触发那个事件 在需要的页面就监听谁
// console.log(this,this.state);
//第二种方式
this.state.$emit('test1',this.val);
this.val = "";
}
},
}
</script>
<style scoped>
</style>
//子组件2
<template>
<div>
<span>你的数据</span>
<ul>
<li v-for="(item,index) in list">
{{list[index]}}
</li>
</ul>
</div>
</template>
<script>
export default {
// 第二种事件总线
data() {
return {
list: []
}
},
created() {
//利用该方法监听自定义事件
this.state.$on('test1',name => {
this.list.push(name);
console.log(this.list)
})
}
}
</script>
<style scoped>
</style>
---------------------------------------------------------------------------------------------------------------
vuex部分
第三种 vuex公共数据池 state
vuex 作为一个公共数据池里面的数据供任意组件使用使用规则
注意
1、各个组件获取数据池中数据方法 this.$store.state.xxx
2、因为涉及数据变化 建议在子组件中使用计算属性来接收数据 (接收数据的三种方式)
//第一种
computed: {
age() {
return this.$store.state.age;
}
},
//第二种
computed:mapState(['name','age','look']),
//第三种
computed:{
...mapState({
storeName:state => state.name,
storeName:state => state.name,
storeName:state => state.name,
})
},
3、鉴于计算属性返回数据的繁琐引入了mapState对象
import {mapState} from 'vuex'
该对象用于对来自数据池的数据进行操作
vuex getters(相当于计算属性)
运用场景如下 当子组件需要的数据要进行加工时 如果使用state中的数据会影响其他组件的数据 此时可以在getters中处理
state相当于data 一般存放固定数据 只有当两个组件的数据变化是同步的时候才可以同时引用data 你变化我也变化
注意:子组件引用时候要区别于state中箭头函数形式 直接填写变量名你就行了
其次getters还可以添加参数如下所示 ,无论是state getters本质上都是对象 可以一对象形式访问各个池中的数据
import {mapGetters} from 'vuex'
vuex store中
getters: {
newList (state,getters) {
console.log(state);
console.log(getters);
console.log(getters.caonima);
return 'hao'
},
caonima() {
return 'nima'
}
},
//组件中
computed:{
...mapState({
stdList:state => state.stdList,
storeName:state => state.name,
storeAge:state => state.age,
}),
...mapGetters({
newList:'newList'
})
},
vuex 之 mutations
到此为止不仅仅利用vuex进行数据处理 到这里开始使用方法函数
同步事件处理
注意 当在非严格模式下可以在mutations之外进行state数据池中数据改动 但是es5严格模式下报错
语法规则:对于mutations参数而言 第一个参数为vuex对象本身 从第二个参数开始为自定义参数
多个参数传递要以对象模式进行接收时也是对象模式 mutations中的方法相当于一个自定义事件 需要用户主动触发
触发语法: this.$store.commit('add',1);
异步事件处理 actions异步更改state数据
在mutations中处理同步事件而言可以处理利用commit方法触发,但是如果mutations中含有异步事件就会报错 不再是同一个作用域 例如定时器
利用actions可以解决这个问题 该函数内部通过定义方法来处理异步事件 原理就是在actions模块中异步触发mutations模块中的方法,在需要的地方不再利用commit触发mutations中的方法而是触发actions里面方法
触发规则 this.$store.dispatch('meess',1);
具体代码如下