Vue - コンポーネント間のデータ通信 (データ転送/共有)

コンポーネント間の通信(データ転送)を実現する仕組み:
1. props設定項目
2. コンポーネントのカスタムイベント
3. グローバルイベントバス
4. メッセージのサブスクリプションとパブリッシング(pubsub)
5. スロット
6. VueX
7. ルーティング経由

小道具構成アイテム

  1. 機能:コンポーネントに外部からデータを受信させます

  1. 渡すデータ:

  1. 親から子への一方向のデータ転送の場合: <Demo name="xxx"/>

  1. ルーティングと連携します。

  1. データを受信します:

  1. 最初の方法 (受信のみ): props:['name']

  1. 2 番目の方法 (制限タイプ): props:{name:String}

  1. 3 番目の方法 (タイプの制限、必要性の制限、デフォルト値の指定):

props:{
	name:{
	type:String, //类型
	required:true, //必要性
	default:'老王' //默认值
	}
}
備考: props は読み取り専用です。Vue の最下層は props の変更を監視します。props を変更すると、警告が発行されます。ビジネスで本当に変更が必要な場合は、props の内容をコピーしてください。データのデータを変更してから、データ内のデータ。

コンポーネントのカスタムイベント

  1. コンポーネント間の通信方法。次の用途に適しています。 子コンポーネント ===> 親コンポーネント

  1. 使用するシーン:

A は親コンポーネント、B は子コンポーネントです。B が A にデータを渡したい場合は、カスタム イベントを A の B にバインドする必要があります (イベントのコールバックは A にあります)

  1. カスタム イベントをバインドします。

  1. 1 つ目の方法は、親コンポーネント内です: <Demo @atguigu="test"/> または <Demo v-on:atguigu="test"/>

  1. 2 番目の方法は、親コンポーネント内で次のようにします。

<Demo ref="demo"/>
......
mounted(){
   this.$refs.xxx.$on('atguigu',this.test)
}
  1. カスタム イベントを 1 回だけトリガーしたい場合は、once 修飾子または $once メソッドを使用できます。

  1. カスタム イベントをトリガーします: this.$emit('atguigu', data)

  1. カスタム イベントのバインド解除: this.$off('atguigu')

  1. コンポーネントはネイティブ DOM イベントにバインドすることもでき、ネイティブ修飾子を使用する必要があります。

  1. 注: this.$refs.xxx.$on('atguigu', callback) を通じてカスタム イベントをバインドする場合、コールバックはメソッドで設定するか、アロー関数を使用する必要があります。そうしないと問題が発生します。


グローバル イベント バス (GlobalEventBus)

  1. コンポーネント間の通信方法。コンポーネント間のあらゆる通信に適しています

  1. グローバル イベント バスをインストールします。

new Vue({
	......
	beforeCreate() {
		Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
	},
    ......
}) 
  1. イベントバスの使用:

  1. データの受信: コンポーネント A がデータを受信したい場合は、コンポーネント A の $bus にカスタム イベントをバインドします。イベントのコールバックはコンポーネント A 自体に残ります。

methods(){
  demo(data){......}
}
......
mounted() {
  this.$bus.$on('xxxx',this.demo)
}
  1. データを提供します: this.$bus.$emit('xxxx', data)

  1. beforeDestroy フックで $off を使用して、現在のコンポーネントで使用されているイベントのバインドを解除するのが最善です。


メッセージのサブスクリプションとパブリッシュ (pubsub)

  1. コンポーネント間の通信方法。コンポーネント間のあらゆる通信に適しています。

  1. 使用手順:

  1. pubsub をインストールします: npm i pubsub-js

  1. インポート: 「pubsub-js」から pubsub をインポートします。

  1. データの受信: A コンポーネントがデータを受信したい場合、A コンポーネント内のメッセージをサブスクライブし、サブスクライブされたコールバックは A コンポーネント自体に残ります。

methods(){
  demo(data){......}
}
......
mounted() {
  this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
}
  1. データを提供します: pubsub.publish('xxx', data)

  1. 購読を解除するには、beforeDestroy フックで PubSub.unsubscribe(pid) を使用するのが最善です。


スロット

  1. 機能:親コンポーネントに html 構造を子コンポーネントの指定された位置に挿入させます。これは、コンポーネント間の通信の方法でもあります。

  1. 親コンポーネント ===> 子コンポーネントに適用されます。

  1. カテゴリ: デフォルト スロット、名前付きスロット、スコープ付きスロット

  1. 使い方:

  1. デフォルトのスロット:

父组件中:
        <Category>
           <div>html结构1</div>
        </Category>
子组件中:
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot>插槽默认内容...</slot>
            </div>
        </template>
  1. 名前付きスロット:

父组件中:
        <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. スコープ付きスロット:

  1. 理解: データはコンポーネント自体に含まれていますが、データに従って生成される構造はコンポーネントのユーザーが決定する必要があります。(ゲームデータはCategoryコンポーネント内にありますが、データを使用してトラバースされる構造はAppコンポーネントによって決定されます)

  1. 特定のエンコーディング:

父组件中:
		<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.コンセプト

Vue での一元的な状態 (データ) 管理を実装し、Vue アプリケーション内の複数のコンポーネントの共有状態を一元管理 (読み取り/書き込み) する Vue プラグインであり、コンポーネント間の通信の手段でもあり、コンポーネント間のあらゆる通信に適しています。

2.いつ使用しますか?

複数のコンポーネントが同じデータを共有する必要がある場合

3. vuex環境を構築する

  1. ファイルの作成: 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. main.js で VM を作成するときにストア構成アイテムを渡します

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

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

4. 基本的な使い方

  1. データの初期化、アクションの構成、ミューテーションの構成、ファイル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. コンポーネントの vuex でデータを読み取ります: $store.state.sum

  1. コンポーネントの vuex のデータを変更します: $store.dispatch('アクション中のメソッド名', data) または $store.commit('ミューテーション中のメソッド名', data)

備考: ネットワークリクエストやその他のビジネスロジックがない場合、コンポーネント内でアクションをスキップすることもできます。つまり、ディスパッチを書かずに直接コミットを書きます。

5. ゲッターの使用

  1. 概念: 状態内のデータを使用前に処理する必要がある場合、ゲッターを使用して処理できます。

  1. ゲッター設定をstore.jsに追加

......

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

//创建并暴露store
export default new Vuex.Store({
	......
	getters
})
  1. コンポーネント内のデータを読み取ります: $store.getters.bigSum

6. 4 つのマップ メソッドの使用

  1. mapState メソッド: 状態内のデータを計算されたプロパティにマップするために使用されます。

computed: {
    //借助mapState生成计算属性:sum、school、subject(对象写法)
     ...mapState({sum:'sum',school:'school',subject:'subject'}),
         
    //借助mapState生成计算属性:sum、school、subject(数组写法)
    ...mapState(['sum','school','subject']),
},
  1. mapGetters メソッド: ゲッター内のデータを計算されたプロパティにマッピングするために使用されます。

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

    //借助mapGetters生成计算属性:bigSum(数组写法)
    ...mapGetters(['bigSum'])
},
  1. mapActions メソッド: アクションとの対話を生成するために使用されるメソッド、つまり $store.dispatch(xxx) を含む関数

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

    //靠mapActions生成:incrementOdd、incrementWait(数组形式)
    ...mapActions(['jiaOdd','jiaWait'])
}
  1. mapMutations メソッド: ミューテーションを含む会話を生成するために使用されるメソッド、つまり $store.commit(xxx) を含む関数

methods:{
    //靠mapActions生成:increment、decrement(对象形式)
    ...mapMutations({increment:'JIA',decrement:'JIAN'}),
    
    //靠mapMutations生成:JIA、JIAN(对象形式)
    ...mapMutations(['JIA','JIAN']),
}
備考:mapActions と mapMutations を使用する場合、パラメーターを渡す必要がある場合は、テンプレートでイベントをバインドするときにパラメーターを渡す必要があります。それ以外の場合、パラメーターはイベント オブジェクトになります。

7. モジュール性 + 名前空間

  1. 目的: コードの保守を容易にし、さまざまなデータの分類をより明確にします。

  1. 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. 名前空間が有効になった後、状態データがコンポーネントに読み込まれます。

//方式一:自己直接读取
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
		}
	}
}

おすすめ

転載: blog.csdn.net/weixin_41606115/article/details/129032268