Vue - data communication between components (data transfer/sharing)

The scheme to realize communication (data transfer) between components:
1. props configuration item
2. custom event of component
3. global event bus
4. message subscription and publishing (pubsub)
5. slot
6. VueX
7. via routing

props configuration item

  1. Function: Let the component receive data from the outside

  1. Pass data:

  1. If one-way data transfer from parent to child: <Demo name="xxx"/>

  1. Cooperate with routing.

  1. Receive data:

  1. The first way (receive only): props:['name']

  1. The second way (restriction type): props:{name:String}

  1. Third way (restrict type, restrict necessity, specify default value):

props:{
	name:{
	type:String, //类型
	required:true, //必要性
	default:'老王' //默认值
	}
}
Remarks: props are read-only. The bottom layer of Vue will monitor your modification of props. If you modify props, a warning will be issued. If the business needs really need to be modified, please copy the content of props to a copy of data, and then modify it The data in data.

Component custom events

  1. A way of communication between components, suitable for: child components ===> parent components

  1. scenes to be used:

A is the parent component, B is the child component, and if B wants to pass data to A, then it must bind a custom event to B in A (the callback of the event is in A) .

  1. Bind custom events:

  1. The first way, in the parent component: <Demo @atguigu="test"/> or <Demo v-on:atguigu="test"/>

  1. The second way, in the parent component:

<Demo ref="demo"/>
......
mounted(){
   this.$refs.xxx.$on('atguigu',this.test)
}
  1. If you want a custom event to be triggered only once, you can use the once modifier, or the $once method.

  1. Trigger a custom event: this.$emit('atguigu', data)

  1. Unbind custom event: this.$off('atguigu')

  1. Components can also be bound to native DOM events, and the native modifier needs to be used.

  1. Note: When binding a custom event through this.$refs.xxx.$on('atguigu', callback), the callback must either be configured in methods or use an arrow function, otherwise this will cause problems!


Global Event Bus (GlobalEventBus)

  1. A way of communication between components, suitable for any communication between components .

  1. Install the global event bus:

new Vue({
	......
	beforeCreate() {
		Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
	},
    ......
}) 
  1. Using the event bus:

  1. Receive data: If component A wants to receive data, then bind a custom event to $bus in component A, and the callback of the event stays in component A itself.

methods(){
  demo(data){......}
}
......
mounted() {
  this.$bus.$on('xxxx',this.demo)
}
  1. Provide data: this.$bus.$emit('xxxx', data)

  1. It is best to use $off in the beforeDestroy hook to unbind the events used by the current component.


Message Subscription and Publishing (pubsub)

  1. A way of communication between components, suitable for any communication between components.

  1. Steps for usage:

  1. Install pubsub: npm i pubsub-js

  1. Import: import pubsub from 'pubsub-js'

  1. Receive data: If A component wants to receive data, it subscribes to the message in A component, and the subscribed callback stays in A component itself.

methods(){
  demo(data){......}
}
......
mounted() {
  this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
}
  1. Provide data: pubsub.publish('xxx', data)

  1. It is best to use PubSub.unsubscribe(pid) in the beforeDestroy hook to unsubscribe.


slot

  1. Function: Let the parent component insert the html structure into the specified position of the child component, which is also a way of communication between components.

  1. Applies to parent component ===> child component.

  1. Categories: default slots, named slots, scoped slots

  1. How to use:

  1. Default slot:

父组件中:
        <Category>
           <div>html结构1</div>
        </Category>
子组件中:
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot>插槽默认内容...</slot>
            </div>
        </template>
  1. Named slots:

父组件中:
        <Category>
            <template slot="center">
              <div>html结构1</div>
            </template>

            <template v-slot:footer>
               <div>html结构2</div>
            </template>
        </Category>
子组件中:
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot name="center">插槽默认内容...</slot>
               <slot name="footer">插槽默认内容...</slot>
            </div>
        </template>
  1. Scoped slots:

  1. Understanding: The data is in the component itself, but the structure generated according to the data needs to be determined by the user of the component. (The games data is in the Category component, but the structure traversed by using the data is determined by the App component)

  1. Specific encoding:

父组件中:
		<Category>
			<template scope="scopeData">
				<!-- 生成的是ul列表 -->
				<ul>
					<li v-for="g in scopeData.games" :key="g">{
    
    {g}}</li>
				</ul>
			</template>
		</Category>

		<Category>
			<template slot-scope="scopeData">
				<!-- 生成的是h4标题 -->
				<h4 v-for="g in scopeData.games" :key="g">{
    
    {g}}</h4>
			</template>
		</Category>
子组件中:
        <template>
            <div>
                <slot :games="games"></slot>
            </div>
        </template>
		
        <script>
            export default {
                name:'Category',
                props:['title'],
                //数据在子组件自身
                data() {
                    return {
                        games:['红色警戒','穿越火线','劲舞团','超级玛丽']
                    }
                },
            }
        </script>

Vuex

1. Concept

A Vue plug-in that implements centralized state (data) management in Vue, and performs centralized management (read/write) on the shared state of multiple components in the Vue application. It is also a way of communication between components, and it is suitable for any Communication between components.

2. When to use it?

When multiple components need to share the same data

3. Build the vuex environment

  1. Create file: src/store/index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions对象——响应组件中用户的动作
const actions = {}
//准备mutations对象——修改state中的数据
const mutations = {}
//准备state对象——保存具体的数据
const state = {}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state
})
  1. Pass in the store configuration item when creating a vm in main.js

......
//引入store
import store from './store'
......

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
	store
})

4. Basic use

  1. Initialize data, configure actions, configure mutations, and operate the file store.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)

const actions = {
    //响应组件中加的动作
	jia(context,value){
		// console.log('actions中的jia被调用了',miniStore,value)
		context.commit('JIA',value)
	},
}

const mutations = {
    //执行加
	JIA(state,value){
		// console.log('mutations中的JIA被调用了',state,value)
		state.sum += value
	}
}

//初始化数据
const state = {
   sum:0
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})
  1. Read the data in vuex in the component: $store.state.sum

  1. Modify the data in vuex in the component: $store.dispatch('method name in action', data) or $store.commit('method name in mutations', data)

Remarks: If there is no network request or other business logic, actions can also be skipped in the component, that is, do not write dispatch, but directly write commit

5. Use of getters

  1. Concept: When the data in the state needs to be processed before use, getters can be used for processing.

  1. Append getters configuration in store.js

......

const getters = {
	bigSum(state){
		return state.sum * 10
	}
}

//创建并暴露store
export default new Vuex.Store({
	......
	getters
})
  1. Read data in the component: $store.getters.bigSum

6. The use of four map methods

  1. mapState method: used to help us map the data in the state to computed properties

computed: {
    //借助mapState生成计算属性:sum、school、subject(对象写法)
     ...mapState({sum:'sum',school:'school',subject:'subject'}),
         
    //借助mapState生成计算属性:sum、school、subject(数组写法)
    ...mapState(['sum','school','subject']),
},
  1. mapGetters method: used to help us map the data in getters to computed properties

computed: {
    //借助mapGetters生成计算属性:bigSum(对象写法)
    ...mapGetters({bigSum:'bigSum'}),

    //借助mapGetters生成计算属性:bigSum(数组写法)
    ...mapGetters(['bigSum'])
},
  1. mapActions method: A method used to help us generate a dialogue with actions, namely: a function containing $store.dispatch(xxx)

methods:{
    //靠mapActions生成:incrementOdd、incrementWait(对象形式)
    ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

    //靠mapActions生成:incrementOdd、incrementWait(数组形式)
    ...mapActions(['jiaOdd','jiaWait'])
}
  1. mapMutations method: A method used to help us generate conversations with mutations, namely: a function containing $store.commit(xxx)

methods:{
    //靠mapActions生成:increment、decrement(对象形式)
    ...mapMutations({increment:'JIA',decrement:'JIAN'}),
    
    //靠mapMutations生成:JIA、JIAN(对象形式)
    ...mapMutations(['JIA','JIAN']),
}
Remarks: When using mapActions and mapMutations, if you need to pass parameters, you need to pass the parameters when binding the event in the template, otherwise the parameters are event objects.

7. Modularity + Namespace

  1. Purpose: Make the code easier to maintain, and make the classification of various data more clear.

  1. Modify store.js

const countAbout = {
  namespaced:true,//开启命名空间
  state:{x:1},
  mutations: { ... },
  actions: { ... },
  getters: {
    bigSum(state){
       return state.sum * 10
    }
  }
}

const personAbout = {
  namespaced:true,//开启命名空间
  state:{ ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    countAbout,
    personAbout
  }
})
  1. After the namespace is enabled, the state data is read in the component:

//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),
  1. 开启命名空间后,组件中读取getters数据:

//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])
  1. 开启命名空间后,组件中调用dispatch

//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
  1. 开启命名空间后,组件中调用commit

//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),


通过路由传递

使用前提:需要先配置好路由

  1. 路由的query参数

  1. 传递参数

<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
				
<!-- 跳转并携带query参数,to的对象写法 -->
<router-link 
	:to="{
		path:'/home/message/detail',
		query:{
		   id:666,
            title:'你好'
		}
	}"
>跳转</router-link>
  1. 接收参数:

$route.query.id
$route.query.title

  1. 路由的params参数

  1. 配置路由,声明接收params参数

{
	path:'/home',
	component:Home,
	children:[
		{
			path:'news',
			component:News
		},
		{
			component:Message,
			children:[
				{
					name:'xiangqing',
					path:'detail/:id/:title', //使用占位符声明接收params参数
					component:Detail
				}
			]
		}
	]
}
  1. 传递参数

<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
				
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link 
	:to="{
		name:'xiangqing',
		params:{
		   id:666,
            title:'你好'
		}
	}"
>跳转</router-link>
特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!
  1. 接收参数:

$route.params.id
$route.params.title

  1. 路由的props配置

作用:让路由组件更方便的收到参数。

{
	name:'xiangqing',
	path:'detail/:id',
	component:Detail,

	//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
	// props:{a:900}

	//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
	// props:true
	
	//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
	props(route){
		return {
			id:route.query.id,
			title:route.query.title
		}
	}
}

Guess you like

Origin blog.csdn.net/weixin_41606115/article/details/129032268