Raison : Pour empêcher plusieurs objets d'instance de composants de partager les mêmes données et de provoquer une pollution des données sous la forme d'une fonction, lorsque initData est utilisé comme fonction d'usine, un nouvel objet de données sera renvoyé. Lorsque les données du composant sont écrites sous forme de fonction, les données sont définies sous la forme d'une valeur de retour de fonction, de sorte que chaque fois que le composant est réutilisé, une nouvelle donnée sera renvoyée avec sa propre portée, similaire à la création d'une donnée privée. pour chaque instance de composant. L'espace de données permet à chaque instance de composant de conserver ses propres données.
L'environnement d'exploitation de ce tutoriel : système windows7, version vue3, ordinateur DELL G3.
1. La différence entre la définition d'instance et de composant de données
Lors de la définition d'une instance de vue, l'attribut de données peut être soit un objet, soit une fonction
const app = new Vue({ el:"#app", // 对象格式 data:{ foo:"foo" }, // 函数格式 data(){ return { foo:"foo" } } })
L'attribut de données défini dans un composant ne peut être qu'un function
Si les données du composant sont directement définies comme un objet
Vue.component('component1',{ template:`<div>组件</div>`, data:{ foo:"foo" }})
, vous recevrez un message d'avertissement
Remarque d'avertissement : les données renvoyées doivent être une fonction dans chaque instance du composant
2. Données du composant fonction de définition et La différence entre les objets
Il a été mentionné ci-dessus que les données des composants doivent être une fonction. Je me demande si vous avez déjà réfléchi à la raison pour laquelle cela se produit ?
Lorsque nous définissons un composant, Vue finira par former une instance de composant via Vue.extend()
Ici, nous imitons le constructeur du composant, définissons l'attribut data et utilisons la forme d'un objet
function Component(){ } Component.prototype.data = { count : 0 }
Créons deux instances de composant
const componentA = new Component() const componentB = new Component()
Modifiez la valeur de l'attribut data du composant composantA, et la valeur dans le composantB change également
console.log(componentB.data.count) // 0 componentA.data.count = 1 console.log(componentB.data.count) // 1
La raison en est que les deux partagent la même adresse mémoire et que le contenu modifié par le composantA affecte également le composantB. [Partage vidéo d'apprentissage : tutoriel vidéo vue, vidéo web front-end]
Si nous utilisons le formulaire d'une fonction, cette situation ne se produira pas (l'adresse mémoire de l'objet renvoyé par la fonction n'est pas la même )
function Component(){ this.data = this.data() } Component.prototype.data = function (){ return { count : 0 } }
Modifier le composant composantA La valeur de l'attribut data, la valeur dans le composantB n'est pas affectée
console.log(componentB.data.count) // 0 componentA.data.count = 1 console.log(componentB.data.count) // 0
Le composant vue peut avoir plusieurs instances, et la fonction est utilisée pour renvoyer un nouveau formulaire de données, de sorte que les données de chaque objet d'instance ne sera pas contaminé par les données des autres objets d'instance
3. Analyse du principe
Tout d'abord, vous pouvez regarder le code des données d'initialisation de la vue. La définition des données peut être une fonction ou un objet.
Emplacement du code source : /vue-dev/src/core/instance/state .js
/vue-dev/src/core/instance/state.js
function initData (vm: Component) { let data = vm.$options.data data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {} ... }
data既能是object也能是function,那为什么还会出现上文警告呢?
别急,继续看下文
组件在创建的时候,会进行选项的合并
源码位置:/vue-dev/src/core/util/options.js
自定义组件会进入mergeOptions进行选项合并
Vue.prototype._init = function (options?: Object) { ... // merge options if (options && options._isComponent) { // optimize internal component instantiation // since dynamic options merging is pretty slow, and none of the // internal component options needs special treatment. initInternalComponent(vm, options) } else { vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) } ... }
定义data会进行数据校验
源码位置:/vue-dev/src/core/instance/init.js
strats.data = function ( parentVal: any, childVal: any, vm?: Component ): ?Function { if (!vm) { if (childVal && typeof childVal !== "function") { process.env.NODE_ENV !== "production" && warn( 'The "data" option should be a function ' + "that returns a per-instance value in component " + "definitions.", vm ); return parentVal; } return mergeDataOrFn(parentVal, childVal); } return mergeDataOrFn(parentVal, childVal, vm); };
Lorsque le composant est créé, les options seront fusionnéesEmplacement du code source : /vue-dev/src/core/util/options.js
rrreee
La définition des données effectuera la vérification des donnéesEmplacement du code source :/vue-dev/src/core/instance/init.js
Ceci Chaque fois que l'instance vm n'est pas définie, entrez le jugement if, si le type de données n'est pas une fonction, un avertissement apparaîtra rrreee
Remarque :
(Partage de vidéos d'apprentissage : développement web front-end, Vidéo de programmation de base)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!