Vue のミックスインと提供/注入

1.ミックスイン

1 はじめに

mixinsミックスインとも呼ばれmixinsコンポーネント間で論理的なコード共有を実現し、コードの重複を減らすために、再利用可能なコード (JS、ライフサイクル フック関数など) を抽出し、それをモジュールとして定義し、複数のコンポーネントに混合することを指します。コンポーネントがmixinsモジュールを使用する場合、mixinsモジュール内のコードがコンポーネントのコードに「混合」されます。コードの「混合」ロジックはコンポーネントのロジックと同じですVue.extend()。具体的なロジックは以下で説明します。

2. 基本的な使い方

モジュールは、 、などのフック関数と同じレベルのフックmixins介してコンポーネント内で呼び出されます。フックの値は、現在のコンポーネントに混合されるモジュールを含む配列です。これらのモジュールの混合順序はフック配列の順序に従って実行され、モジュールにライフサイクル フック関数が含まれている場合、モジュール内のフック関数の実行順序は、コンポーネント自体のフック関数よりも前になります。datamountedmethodsmixinsmixinsmixinsmixins

ケースコード:
// 定义一个mixin模块 mixin.js
export default {
    
    
  created: function () {
    
     console.log('这里是mixin1模块的created') }
}

// 在组件实例中引入并使用定义的mixin模块
// 引入mixin模块
import mixin from "../mixins/mixin";
export default {
    
    
  created: function () {
    
     console.log('这里是组件本身的created') },
  // 使用mixin模块
  mixins: [mixin]
}
結果:

ここに画像の説明を挿入

3. オプションのマージ

コンポーネントとインポートされたmixinsモジュールに同じ名前のオプションが含まれている場合、これらのフックは次のルールに従ってマージされます (Vue.extend()マージ ロジックは同じです)。

mixinsモジュール内のdataデータオブジェクトdataとコンポーネントのデータを再帰的にマージし、同名のデータが存在する場合はコンポーネント内のデータ値を取得します。

コンポーネントが複数のmixinsモジュールを導入する場合、mixinsフック配列の順序に従ってマージされますmixinsモジュール間に同名のデータがある場合は、最後のmixinsモジュールのデータ値が取得されます もちろん、コンポーネント内にもデータが存在する場合は、コンポーネント内のデータ値が取得されます

ケースコード:
// 定义一个mixin1.js模块
export default {
    
    
  data() {
    
    
    return {
    
    
      a: 1, // 第一个混入模块中的变量a
      b: 11 // 第一个混入模块中的变量b
    }
  },
}
// 定义一个mixin2.js模块
export default {
    
    
  data() {
    
    
    return {
    
    
      a: 2, // 第二个混入模块中的变量a
      b: 22 // 第二个混入模块中的变量b
    }
  },
}

// 在组件实例中引入并使用定义的mixin模块
// 引入两个mixin模块
import mixin1 from "../mixins/mixin1";
import mixin2 from "../mixins/mixin2";
export default {
    
    
  data() {
    
    
    return {
    
    
      b: 0, // 组件内的变量b
    };
  },
  mounted() {
    
    
    // 组件内不存在这个变量 两个混入模块存在同名变量 最终值取决于模块引用顺序
    console.log("经过合并后变量a的值是-----", this.a);
    // 组件内存在这个变量 最终值取组件内的值
    console.log("经过合并后变量b的值是-----", this.b);
  },
  // 使用两个mixin模块 注意先后顺序 决定同名变量的最终取值
  mixins: [mixin1, mixin2],
}
結果:

ここに画像の説明を挿入

mixinsモジュール内のフック関数はコンポーネント内の同名のフック関数と配列に結合されて順番に実行され、モジュールmixins内のフック関数はコンポーネント内の同名のフック関数よりも先に呼び出されて実行されます。名前が異なるフック関数は、フック関数の順序で実行されます。

コンポーネントが複数のmixinsモジュールを導入する際、mixinsモジュール間に同名のフック関数があった場合、mixinsフック配列の順序に従って配列にマージされます。並び順は実行順序と同じです。最上位のモジュール内の同名のフック関数が先に実行され、その後に同名のフック関数が実行され、最後にコンポーネント自身の同名のフック関数が実行されますmixins

ケースコード:
// 定义一个mixin1.js模块
export default {
    
    
  created: function () {
    
     console.log('这里是mixin1模块的created') },
}
// 定义一个mixin2.js模块
export default {
    
    
  created: function () {
    
     console.log('这里是mixin2模块的created') },
  mounted: function () {
    
     console.log('这里是mixin2模块的mounted') },
}

// 在组件实例中引入并使用定义的mixin模块
// 引入两个mixin模块
import mixin1 from "../mixins/mixin1";
import mixin2 from "../mixins/mixin2";
export default {
    
    
  created() {
    
    
    console.log("这里是组件本身的created");
  },
  // 使用两个mixin模块 注意先后顺序 决定同名钩子函数的执行顺序
  mixins: [mixin1, mixin2],
}
結果:

ここに画像の説明を挿入

③オブジェクトに相当するmixinsモジュール内のオプションは、コンポーネント内の対応するオプションとマージされて 1 つのオブジェクトとなり、オブジェクト内のキー名が競合する場合は、コンポーネント内のキー名に対応する値が取得されます。methodscomponents

コンポーネントが複数のmixinsモジュールを導入するとき、mixinsモジュール間のオプションに同じ名前の競合がある場合、mixinsフック配列の順序に従って上書きされます。後のミックスインは前のミックスインをオーバーライドし、キー名に対応する値は最後のモジュールの対応する値を取得します。もちろん、コンポーネント内にもキー名が存在する場合は、最終的にはコンポーネント内の対応する値が取得されますmixins

ケースコード:
// 定义一个mixin1.js模块
export default {
    
    
    methods: {
    
    
    test() {
    
    
      console.log('这里是mixin1模块methods中的test函数')
    },
    test1() {
    
    
      console.log('这里是mixin1模块methods中的test1函数')
    }
  },
}
// 定义一个mixin2.js模块
export default {
    
    
  methods: {
    
    
    // 如果mixin模块之间存在键名冲突 则以组件中mixin数组的引用顺序为准
    // 取排序最后的键名对应的值
    test1() {
    
    
      console.log('这里是mixin2模块methods中的test1函数')
    }
  },
}

// 在组件实例中引入并使用定义的mixin模块
// 引入两个mixin模块
import mixin1 from "../mixins/mixin1";
import mixin2 from "../mixins/mixin2";
export default {
    
    
  mounted() {
    
    
    this.test();
    this.test1();
  },
  // 使用两个mixin模块 注意先后顺序 决定键名冲突的最终结果
  mixins: [mixin1, mixin2],
  methods: {
    
    
    // 如果mixin模块与组件本身键名冲突 则以组件为最终结果
    test() {
    
    
      console.log("这里是组件本身methods中的test函数");
    },
  },

}
結果:

ここに画像の説明を挿入

要約:

コンポーネントが複数の を使用する場合mixins、その順序が重要になります。mixinsオプション間に矛盾がある場合、後者がmixins前者をオーバーライドするためですmixinsまた、同名のフック関数の実行順序もmixins複数の順序に依存します。

コンポーネントとmixinsオプションの間に矛盾がある場合は、コンポーネントが優先されます。

複数の を使用する場合はmixins、名前の競合に注意してください。

4. グローバルミックスイン

上記の例はmixinsコンポーネントにモジュールを順番に導入する例ですが、複数のコンポーネント、あるいはすべてのコンポーネントにモジュールを導入したい場合mixins、各コンポーネントに一度ずつモジュールを導入するのは非常に面倒です。この時点で、グローバル ミックスイン機能を使用できるようになります。

グローバル ミックスインとは、ファイル内のグローバル Vue インスタンスが作成される前に、メソッドを通じて宣言されたmixinsモジュールをVue にマウントすることを指します。この機能はモジュールをグローバルに導入するのと同等であり、個別に作成されたすべての Vue ページ インスタンスとコンポーネントに影響を与えるため、この機能は注意して使用してください。main.jsVue.mixin()mixins

グローバルに混合されたmixinsモジュールにライフサイクル フック関数が含まれている場合、フック関数の実行回数は現在のページに含まれる Vue インスタンスの数に応じて決定され、main.js ファイル内のグローバル Vue インスタンスもカウントされます。

ケースコード:
// 定义一个allmixin.js 模块
export default {
    
    
  created: function () {
    
     console.log('这里是全局mixin模块的created') },
  methods: {
    
    
    test() {
    
    
      console.log('这里是全局mixin模块methods中的test函数')
    }
  },
}

// 在main.js中引入并进行全局混入
import Vue from 'vue'
import App from './App.vue'
import allMixin from './mixins/allMixin'
// 一定要在 new Vue 之前  否则不起作用
Vue.mixin(allMixin)
// 创建全局Vue实例
new Vue({
    
    
  render: h => h(App),
}).$mount('#app')

// 此时的页面结构
// mian.js的new Vue -> APP.vue -> test.vue
結果:

ここに画像の説明を挿入

5. カスタムオプション

グローバル ミックスインをカスタム オプションと組み合わせて使用​​できるようにする必要がありますthis.$options。カスタム オプションを使用するコンポーネントのみが関連ロジックをトリガーするため、mixinsモジュール内の一部のコードの範囲が制限されます。

ケースコード:
// 定义一个allmixin.js 模块
export default {
    
    
  created: function () {
    
    
    // 自定义选项 并接收传递的值
    const myOptionValue = this.$options.myOption
    // 输出传递的值
    if (myOptionValue) {
    
    
      console.log('-*------', myOptionValue)
    }
  },
}

// 在main.js中引入并进行全局混入
import Vue from 'vue'
import App from './App.vue'
import allMixin from './mixins/allMixin'
// 一定要在 new Vue 之前  否则不起作用
Vue.mixin(allMixin)
// 创建全局Vue实例
new Vue({
    
    
  render: h => h(App),
}).$mount('#app')

// 在组件使用全局混入中自定义的选项
export default {
    
    
    data() {
    
    
        return {
    
    }
    },
    // 使用自定义选项
    myOption: "这是我向自定义选项传递的字符串",
}
結果:

ここに画像の説明を挿入

モジュールmixins内のカスタム オプションがマージされると、デフォルトの戦略が使用され、既存の値が単純にオーバーライドされます。もちろん、次の方法Vue.config.optionMergeStrategiesでマージ ロジックをカスタマイズすることもできます。

// 自定义合并逻辑
Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {
    
    
  // 返回合并后的值
}
// 或者
// 采用现有逻辑 与methods相同
Vue.config.optionMergeStrategies.myOption = Vue.config.optionMergeStrategies.methods

二、provide/inject

1 はじめに

provide/inject は、Vue バージョン 2.2.0 の新機能ですpropsこの機能は、React フレームワークのコンテキスト機能と非常に似ています。

ただし、provide/inject 機能を過度に使用すると、コンポーネント間の結合が増加し、コンポーネントの再利用性が低下するため、この機能を使用する場合は注意し、乱用しないようにしてください。また、provideと のバインディングinjectは非応答であり、渡されたデータはデータの変更に自動的に応答しませんので、データの変更に応答したい場合は、dataまたは を使用してくださいcomputed

2、提供する

provide子孫コンポーネントにデータを渡すには、先祖コンポーネントでオプション 渡されるデータは、プリミティブ型、オブジェクト、関数など、あらゆる種類のデータにすることができます。

provideオプションは ES2015 シンボルのキーとしての使用をサポートしますが、ネイティブにサポートしSymbolReflect.ownKeys

ケースコード:
// provide 的选项值为一个对象
export default {
    
    
    data() {
    
    
        return {
    
    }
    },
    provide: {
    
    
        a: "这是祖先组件向后代组件传递的字符串数据",
    	b: {
    
    
      		c: "这是祖先组件向后代组件传递的对象数据",
    	},
    	f: function () {
    
    
      		console.log("这是祖先组件向后代组件传递的函数数据");
    	},
    },
}

// provide 的选项值为一个返回值为对象的函数
export default {
    
    
    data() {
    
    
        return {
    
    }
    },
    provide() {
    
    
    	return {
    
    
      		 a: "这是祖先组件向后代组件传递的字符串数据",
        	 b: {
    
    
          	 	c: "这是祖先组件向后代组件传递的对象数据",
        	 },
        	 f: function () {
    
    
          	 	console.log("这是祖先组件向后代组件传递的函数数据");
        	 },
    	  };
  	  },
}

3、注入

オプションは、inject祖先コンポーネントによって渡されたデータを受信するために子孫コンポーネントで使用されます。オプションの値は文字列配列 (推奨) またはオブジェクトです。provide文字列配列の形式を使用し、配列要素がobject内の要素に対応しkey、祖先コンポーネントによってフォームを通じて渡される対応するデータにアクセスすることをお勧めします。オブジェクト フォームを使用する場合は、this.数组字符串元素キーと値のペアを通じてデータを受信する必要があり、キー名は現在のコンポーネント内のアクセス名を表し、オブジェクトに対応する文字列であり、祖先コンポーネントによってフォームを通じて渡される対応するデータにアクセスvalueますprovidekeythis.键名

ケースコード:
// inject 的选项值为一个字符串数组(推荐)
export default {
    
    
    data() {
    
    
        return {
    
    }
    },
	inject: ["a", "b", "f"],
}

// inject 的选项值为一个对象(不推荐)
export default {
    
    
    data() {
    
    
        return {
    
    }
    },
	inject: {
    
    
    	a: "a",
    	b: "b",
    	f: "f",
  	},
}

// 在后代组件中通过inject接收传递的数据之后 调用传递的数据
mounted() {
    
    
    console.log("inject接收的祖先组件传递过来的字符串数据-----", this.a);
    console.log("inject接收的祖先组件传递过来的对象数据-----", this.b);
    console.log("inject接收的祖先组件传递过来的函数数据-----", this.f);
},
結果:

ここに画像の説明を挿入

4. 高度な知識

① Vue のバージョン 2.2.1 以降では、inject子孫コンポーネントから渡されるデータを事前に取得しpropsdata初期化するため、 のinjectデータを使用したり、propsおよびdataのデータにデフォルト値を設定したりすることができます。

export default {
    
    
    inject: ['foo'],
    props: {
    
    
      a: {
    
    
          default() {
    
    
              return this.foo
          }
      }
    },
    data() {
    
    
        return {
    
    
            b: this.foo
        }
    },
}

② Vue バージョン 2.5.0 以降では、injectオプション値のオブジェクト形式でデータのデフォルト値を設定できるようになり、祖先コンポーネントでオプションにすることができます。つまり、データが渡されない場合でも、子孫コンポーネントは正常に動作します。fromプロパティはデータ ソースを設定し、defaultプロパティはデフォルト値を設定します。

propsデフォルト値の設定と同様に、非プリミティブ値 (複雑なデータ型) をデフォルト値として直接使用すると、その値はすべてのサブコンポーネント インスタンス間で共有参照となり、相互に影響しますしたがって、デフォルト値を使用するたびに、同じ参照を共有するのではなく、新しいコピーを取得できるように、非プリミティブ値 (複雑なデータ型) に対してファクトリ メソッドを使用する必要があります。

export default {
    
    
    inject: {
    
    
        // 当组件内名称与祖先组件的key相同时,可省略form属性
    	foo: {
    
     default: 'foo' },
        // 当组件内名称与祖先组件的key不同时,需要通过form属性指定对应的数据
        bar: {
    
    
            from: 'barFather',
            default: 'bar'
        },
        // 对复杂数据类型使用一个工厂方法
        arr: {
    
    
            from: 'arr',
            default: () => [1, 2, 3]
        },
  	},
    data() {
    
    
        return {
    
    }
    },
}

3. 参考文献

Vue公式ドキュメント

チャットGPT

おすすめ

転載: blog.csdn.net/weixin_45092437/article/details/131542674