Mixins y proporcionar/inyectar para Vue

1. mezclas

1. Introducción

​También conocido comomixins mix-in, se refiere a extraer código reutilizable (JS, funciones de enlace de ciclo de vida, etc.), definirlo como un mixinsmódulo y luego mezclarlo en múltiples componentes, para lograr compartir el código lógico entre los componentes y reducir la duplicación de código. Cuando un componente usa mixinsun módulo, mixinsel código dentro del módulo se "mezclará" con el código del componente. La lógica de "mezcla" del código es la misma Vue.extend()que la del componente. La lógica específica se explica a continuación.

2. Uso básico

​El módulomixins se llama en el componente a través de un enlace al mismo nivel que las funciones de enlace como data, etc. El valor del enlace es una matriz, que contiene los módulos que se mezclarán en el componente actual. El orden de mezcla de estos módulos se ejecuta de acuerdo con el orden de la matriz de enlaces, y mountedsi el módulo contiene funciones de enlace de ciclo de vida, el orden de ejecución de las funciones de enlace en el módulo es anterior a las funciones de enlace del componente mismo.methodsmixinsmixinsmixinsmixins

Código de caso:
// 定义一个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]
}
Resultados de la:

inserte la descripción de la imagen aquí

3. Fusión de opciones

​ Cuando el componente y el mixinsmódulo importado contienen opciones con el mismo nombre, estos ganchos se fusionarán de acuerdo con las siguientes reglas ( Vue.extend()la lógica de fusión es la misma):

El objeto de datos mixinsen el módulo se fusionará recursivamente con los datos del componente.Si hay datos con el mismo nombre, se tomará el valor de los datos en el componente.datadata

Cuando un componente introduce varios mixinsmódulos, se combinarán mixinsde acuerdo con el orden de la matriz de ganchos. Si hay datos con el mismo nombre entre los módulos, se tomará mixinsel valor de los datos del último módulo. Por supuesto, si los datos también existen en el componente, se tomará el valor de los datos en el componente.mixins

Código de caso:
// 定义一个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],
}
Resultados de la:

inserte la descripción de la imagen aquí

mixinsLa función de gancho en el módulo se combinará con la función de gancho del mismo nombre en el componente en una matriz y se ejecutará en secuencia, y la función de mixinsgancho en el módulo se llamará y ejecutará antes que la función de gancho del mismo nombre en el componente. Las funciones de enlace con diferentes nombres todavía se ejecutan en el orden de las funciones de enlace.

​ Cuando un componente introduce múltiples mixinsmódulos, si mixinshay funciones de enlace con el mismo nombre entre los módulos, se fusionarán mixinsen una matriz de acuerdo con el orden de las matrices de enlace. El orden de disposición es el mismo que el orden de ejecución. Las funciones de enlace con el mismo nombre mixinsen los módulos con el orden más alto se ejecutarán primero, y aquellas con el mismo nombre se ejecutarán después, y finalmente se ejecutarán las funciones de enlace con el mismo nombre del componente.

Código de caso:
// 定义一个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],
}
Resultados de la:

inserte la descripción de la imagen aquí

③ Las opciones mixinsen el módulo que methodsson componentsequivalentes a los objetos se fusionarán con las opciones correspondientes dentro del componente en un solo objeto. Cuando el nombre de la clave en el objeto entre en conflicto, se tomará el valor correspondiente al nombre de la clave en el componente.

Cuando un componente introduce múltiples mixinsmódulos, si mixinshay un conflicto del mismo nombre entre las opciones entre los módulos, se sobrescribirá mixinsde acuerdo con el orden de la matriz de ganchos. Los mixins posteriores anularán los mixins anteriores, y el valor correspondiente al nombre de la clave tomará el valor correspondiente en el último módulo. Por supuesto, si el nombre de la clave también existe en el componente, eventualmente se tomará el valor correspondiente en el componente mixins.

Código de caso:
// 定义一个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函数");
    },
  },

}
Resultados de la:

inserte la descripción de la imagen aquí

Resumir:

Cuando un componente usa más de uno mixins, su orden es importante. Porque mixinscuando hay un conflicto entre las opciones, esta última mixinsprevalecerá sobre la primera mixins. Y el orden de ejecución de la función gancho con el mismo nombre también depende del mixinsorden de los múltiples.

Cuando exista un conflicto entre un componente y mixinsuna opción, prevalecerá el componente.

Cuando utilice múltiples mixins, recuerde prestar atención a los conflictos de nombres.

4. Combinación global

​ Los ejemplos que dimos anteriormente son para introducir mixinsmódulos secuencialmente en componentes.Si queremos introducir un módulo en varios componentes, o incluso en todos los componentes mixins, será demasiado engorroso introducirlo una vez en cada componente. En este punto, podemos usar la función de mezcla global.

La combinación global se refiere al montaje del mixinsmódulo declarado en Vue main.jsa través de un método antes de que se cree la instancia global de Vue en el archivo . Vue.mixin()Su función es equivalente a la introducción mixinsde módulos a nivel mundial, lo que afectará a cada instancia y componente de la página Vue creada individualmente, ¡así que use esta función con precaución! ! !

​ Si el mixinsmódulo combinado globalmente contiene una función de enlace de ciclo de vida, la cantidad de veces que se ejecutará la función de enlace se determinará de acuerdo con la cantidad de instancias de Vue contenidas en la página actual, y la instancia global de Vue en el archivo main.js también contará.

Código de caso:
// 定义一个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
Resultados de la:

inserte la descripción de la imagen aquí

5. Opciones personalizadas

Deberíamos poder this.$optionsusar mixins globales en combinación con opciones personalizadas. Solo los componentes que usan opciones personalizadas activarán la lógica relevante, lo que limita mixinsel alcance de algunos códigos en el módulo:

Código de caso:
// 定义一个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: "这是我向自定义选项传递的字符串",
}
Resultados de la:

inserte la descripción de la imagen aquí

mixinsCuando se fusionan las opciones personalizadas en el módulo Por supuesto, también podemos Vue.config.optionMergeStrategiespersonalizar la lógica de combinación mediante:

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

Dos, proporcionar/inyectar

1. Introducción

​esprovide/inject una nueva función de Vue en la versión 2.2.0. Esta función puede realizar la transferencia de datos entre niveles de los componentes antecesores a sus componentes descendientes, sin importar cuántos niveles de componentes estén separados entre los dos. En comparación con el método de transferencia tradicional, reduce las engorrosas operaciones de transferencia de datos y mejora la legibilidad y el mantenimiento del código props. Esta función es muy similar a la función de contexto del marco React.

Sin embargo, el uso excesivo de provide/inject funciones aumentará el acoplamiento entre los componentes y reducirá la reutilización de los componentes, así que tenga cuidado al usar esta función y no abuse de ella. Además, el enlace de providey injectno responde, y los datos pasados ​​no responden automáticamente a los cambios de datos. Si desea responder a los cambios de datos, utilice datao computed.

2, proporcionar

Las opcionesprovide deben usarse en los componentes antecesores para pasar datos a los componentes descendientes. El valor de la opción es un objeto o una función que devuelve un objeto. Las propiedades del objeto son los datos que se pasarán a los componentes descendientes. Los datos pasados ​​pueden ser cualquier tipo de datos, como tipos primitivos, objetos, funciones, etc.

Las opciones admiten el uso de símbolos ES2015 como claves, pero solo funcionan en entornos que provideadmiten SymbolyReflect.ownKeys

Código de caso:
// 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, inyectar

Las opcionesinject se utilizan en componentes descendientes para recibir datos pasados ​​por componentes antepasados. El valor de la opción es una matriz de cadenas (recomendado) o un objeto. Se recomienda más usar la forma de una matriz de cadenas, donde los elementos de la matriz corresponden a los del provideobjeto key, y this.数组字符串元素acceder a los datos correspondientes pasados ​​por el componente ancestro a través del formulario; si usa el formulario de objeto, necesita recibir los datos a través del par clave-valor, el nombre de la clave representa el nombre de acceso en el componente actual, que es una cadena, correspondiente al objeto, y acceder a los datos correspondientes pasados ​​por el componente ancestro a valuetravés providedel keyformulario this.键名.

Código de caso:
// 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);
},
Resultados de la:

inserte la descripción de la imagen aquí

4. Conocimientos avanzados

① Después de la versión 2.2.1 de Vue, injectlos datos pasados ​​por los componentes descendientes se obtendrán antes propsy datase inicializarán, por lo que podemos usar injectlos datos de entrada y establecer valores predeterminados para los datos propsde entrada y dataentrada.

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

② Después de la versión 2.5.0 de Vue, podemos injectestablecer el valor predeterminado para los datos en la forma de objeto del valor de la opción, haciéndolo opcional en el componente principal, es decir, cuando no se pasan los datos, el componente descendiente aún puede funcionar normalmente. fromLas propiedades establecen la fuente de datos, defaultlas propiedades establecen el valor predeterminado.

De manera similar a propsestablecer un valor predeterminado, si usa directamente un valor no primitivo (tipo de datos complejo) como valor predeterminado, se convertirá en una referencia compartida entre todas las instancias de subcomponentes, lo que se afectará entre sí. Por lo tanto, debemos usar un método de fábrica para valores no primitivos (tipos de datos complejos) para que cada vez que usemos el valor predeterminado obtengamos una copia nueva en lugar de compartir la misma referencia.

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. Referencias

Documentación oficial de Vue

ChatGPT

Supongo que te gusta

Origin blog.csdn.net/weixin_45092437/article/details/131542674
Recomendado
Clasificación