prps和$emit
props
父传子
父组件用自定义属性传值,子组件通过props接收并使用
父组件
<Child :msg="data"/>
data() {
return {
data: 'Welcome to Vue'
}
}
子组件
<h1>{{ msg }}</h1>
props: {
msg: {
type: String,
default: ''
},
}
$emit
父组件绑定自定义事件名=“自定义事件函数”
子组件通过 $emit('自定义事件名',传值) ,触发父级进行传值
eventBug事件总线
兄弟传值
1、创建一个空白Vue对象 ---eventBug.js新建(
2、兄弟组件分别引入空白对象文件
3、兄弟组件1通过 $emit(‘事件名’,值)进行触发
4、兄弟组件2 通过$on(‘事件名’,函数体)接收
vue空白对象---eventBus.js
import Vue from 'vue'
export default new Vue()
父组件
<child1></child1>
<child2></child2>
import child1 from './communication/child.vue'
import child2 from './communication/grandson.vue'
components: {
child1,
child2
}
兄弟组件child1
<button @click="btnSub">点我就减1:{{ message }}</button>
import bus from './eventBus.js'
export default {
name: 'child1',
data() {
return {
message: 100,
}
},
methods: {
btnSub() {
--this.message
bus.$emit('sendBybus', this.message)
},
},
}
兄弟组件child2
<button @click="btnSubtwo">点我就减2:{{ message }}</button>
export default {
name: 'child2',
data() {
return {
message: 100,
}
},
mounted() {
// 接受oen组件传递过来的值,,sendbus标识需要跟oen保持一致
bus.$on('sendBybus', (data) => {
this.message = data
})
},
methods: {
btnSubtwo() {},
},
}
注意:兄弟传值,是单向数据流
children $refs
$children
父访问子
返回的是一个组件集合,若不清楚子组件顺序,可使用索引操作
注意: 不建议使用,若动态插入标签元素,索引则不唯一,无法具体访问某一个指定元素
缺点: 利用$children获取到的数组类型,访问其中的组件必须通过索引值。
当子组件过多时,往往不能确定他的索引值,所以引进了新的父访子的方式$refs
父组件
<child ref="child1"></child>
mounted() {
console.log(this.$children)
const children = this.$children[0]
//判断子组件是否等于child1
//$vnode.data.ref是$children上固定写法
if (children.$vnode.data.ref === 'child1') {
console.log(children.msg)//hello vue
children.message('hello')
}
},
子组件
<div>
儿子
</div>
data() {
return {
msg: 'hello vue',
imgs: 100,
}
},
methods: {
message(value) {
console.log(value)//hello
},
}
$parent
子组件中,this.$parent指向父组件
this.$parent.xxx=200
this.$parent.fn()
子组件1
<button @click="sendDataToChild2">发送</button>
name: 'child1',
methods: {
sendDataToChild2() {
this.$parent.$emit('send', '我是子组件1')
},
},
子组件2
<div>儿子2</div>
export default {
name: 'child2',
mounted() {
this.$parent.$on('send', (value) => {
console.log(value)
})
},
}
父组件
<child1></child1>
<child2></child2>
components: {
child1,
child2,
},
mounted() {
console.log(this.$parent)//Vue
},
}
provide inject
父传孙
父组件通过provide传值,
孙组件通过inject接收数据
父传孙、父传子是同样用法
父组件
<child ></child>
export default {
components: {
child,
},
provide() {
return { msg: "hello vue" };
},
}
子组件
<grandson ></grandson>
孙组件
<div>{{ msg }}</div>//hello vue
export default {
inject: ['msg'],
}
父传子
父组件
<child ></child>
export default {
components: {
child,
},
provide() {
return { msg: "hello vue" };
},
}
子组件
<div>
子组件
<hr />
{{ msg }}//hello vue
<grandson></grandson>
</div>
import grandson from './grandson.vue'
export default {
components: {
grandson,
},
inject: ['msg'],
}
listeners
父传孙
子组件通v-bind=" $attrs " 搭桥,孙组件通过props接收并使用;
父组件
子组件
孙组件
孙传父
父组件绑定"自定义这函数名=自定义事件函数",
子组件通过v-on=“ $listeners ” 搭桥,
孙组件通过 $emit ('父组件自定义函数名',传值)
孙组件
<button @click="send">点我呀</button>
methods: {
send() {
this.$emit('event', '快点我呀')
},
},
子组件
<grandson v-on="$listeners"></grandson>
父组件
<child @event="test"></child>
test(value) {
console.log(value)//快点我呀
},
子传父
通过 $listeners进行传值
子组件通过this.$listeners.父组件自定义函数名(传值)
父组件绑定自定义函数名=“自定义事件处理函数” 接收值并使用
子组件
<button @click="send">发送</button>
send() {
this.$listeners.cc('hello vue')
},
父组件
<child @cc="message"></child>
message(value) {
console.log(value)//hello vue
},
Vuex
uex :全局状态管理库,用来进行全局数据流的管理
//1 导入vuex
import Vuex from 'vuex'
//2 注册vuex
Vue.use(Vuex)
//3 实例化一个Vuex
const store = new Vuex.Store({
state:{},
mutations:{},
actions:{},
getters:{},
modules:{}
})
//4 sotre共享数据对象挂载到vue实例
new Vue({
render: (h) => h(App),
// 将创建的共享数据对象,挂载到 Vue 实例中
// 所有的组件,就可以直接从 store 中获取
store,
}).$mount('#app')
state
存储数据
state: {
// 存储状态
count: 0
},
原始方式
用法:this.$store.state.数据名
this.$store.state.count
辅助函数形式
用法:
1、从vuex中导入
import { mapState } from 'vuex'
2、在计算属性中映射到当前页面
...mapState(['数据名'])
import { mapState } from 'vuex'
computed: {
// 2.1 监听count变化
// count() {
// return this.$store.state.count
// },
// 3.2 利用扩展运算符把sotre 中的count映射到计算属性中
...mapState(['count']),
},
mutations
mutations: 修改state数据,多用于同步操作
mutations: {
// updateStae(state) {
// state.count += 1
// },
// 传参,
updateStae(state, payload) {
console.log(state)
state.count += payload
},
}
原始方式
用法:
1、 mutations中自定义函数
2、通过this.$store.commit ("触发自定义函数",传值)
<button @click="test">+1(原始形式)</button>
methods: {
test() {
// 调用mutation方法,提交mutation
// commit(mutation函数名称)
this.$store.commit('updateStae', 5)
}
}
辅助函数形式
1、、从vuex中导入mapMutations
import { mapMutations} from 'vuex'
2、在方法中映射到当前组件
...mapMutations(['updateStae']),
<button @click="updateStae(50)">+100(辅助函数形式)</button>
import { mapMutations} from 'vuex'
methods: {
// 方式二、把state中的updateStae函数映射到这个组件中
...mapMutations(['updateStae']),
}
actions
actions:不可直接修改state数据,需提交mutations函数,进而让mutations修改state数据,存放异步操作
actions: {
// 存放的也是一个个的方法
// 第一个参数 执行的上下文对象
// context相当于组件中的this.$store store的运行实例
getAsyancCount(context, parmas) {
//做异步请求,模拟异步请
setTimeout(() => {
//接收dispath数据,并提交给mutations中的updateStae函数,进行修改数据
context.commit('updateStae', parmas)
}, 1000)
}
原始方式
用法:
1、actions中自定义函数
2、通过this.$store. dispatch("触发自定义函数",传值)
<button @click="test1">异步调用(原始形式)</button>
methods:{
test1() {
this.$store.dispatch('getAsyancCount', 111)
},
}
辅助函数形式
1、、从vuex中导入mapMutations
import { mapMuta tion s} from 'vuex'
2、在方法中映射到当前组件,绑定的函数上传值
... mapMutations (['updateStae'])
<button @click="getAsyancCount(333)">异步调用(辅助函数形式)</button>
import { mapActions} from 'vuex'
methods:{
...mapActions(['getAsyancCount']),
}
getters
getters:存放基于state计算出来的一些值(计算属性)
state: {
// 存储状态
count: 0,
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
}
原始方式
1、查看基于state存放的数据,进行数据查找
2、用 $store.getters.数据名查看
getters: {
// 拿到相应的vuex的计算属性
filterList(state) {
return state.list.filter((item) => item > 5)
}
//第二种简化写法
//filterList: (state) => tate.list.filter((item) => item > 5)
}
<p>原始形式getters:{{ $store.getters.filterList }}</p>
辅助函数方式
1、导入mapGetters
import {mapGetters } from 'vuex'
2、计算属性中映射到当前页面
...mapGetters(['数据名']
<p>辅助形式getters:{{ filterList }}</p>
import {mapGetters } from 'vuex'
computed: {
// 导入计算属性名
// 将getters中的计算属性导入到组件的计算属性中
...mapGetters(['filterList']),
}
modules
modules:分模块,大型项目使用
注意点:
分模块时,默认mutations、actions、getters注册全局,一般会开启命名空间
namespaced:true
若想进行分模块,则需要在为每个moduls起个模块名,在分别将state、mutations、actions放进对应模块,需为每个模块加上命名空间,防止被全局或者其他模块任意访问没有隐私
ps----下文中的user、setting即是自定义取的模块名
modules: {
// 设置模块的子属性
user: {
namespaced: true,
state: {
token: '12345',
},
mutations: {
updateToken(state) {
state.token = '67890'
},
},
},
setting: {
namespaced: true,
state: {
name: 'vuex实例',
},
},
}
原始方式
1、 $store.state.模块名.模块中state里的值
<p>用户的token:{{ $store.state.user.token }}</p>
<p>网站名称:{{ $store.state.setting.name }}</p>
getter快捷访问方式
1、getter监听模块state中的数据
2、用箭头函数形式
<p>快捷访问方式:{{ token }}</p>
<p>快捷访问方式:{{ name }}</p>
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['token', 'name']),
},
getters: {
// 监听user/setting模块下state中的值
token: (state) => state.user.token,
name: (state) => state.setting.name,
},
更新值
原始方式
user/updateToken路径,表示user模块下的updateToken函数
传参用法跟非模块一样,只不过多了一个模块名/模块下的某个函数名, 用来触发或者提交数据,进而修改相应模块中state的值
<button @click="updateToken">更新子模块的token</button>
methods: {
updateToken() {
// 解决方案,采用路径方式,表示user模块下的updateToken函数
this.$store.commit('user/updateToken')
}
}
辅助函数形式
<button @click="updateToken">辅助函数形式token</button>
metods:{
...mapMutations(['user/updateToken']),
}
调用createNamespacedHelpers方式
<button @click="text">调用子模块的mapMutations</button>
import {createNamespacedHelpers } from 'vuex'
//mapMutations这个是 user中的
const { mapMutations } = createNamespacedHelpers('user')
methods:{
// 解决方式3:采用关联数组形式
text() {
this['user/updateToken']()
}
}
sync
父传子时,子组件想要修改父组件传过来的值,需给父组件添加sync修饰符,而子组件通过 $emit("update:变量名",值) 触发父组件对其赋新值。
注意: $emit("update:flag",false),除变量名及值外,其他都是固定写法