


Parlons du problème de pointage de ceci dans vue2.x. Pourquoi pointe-t-il vers l'instance de vue ?
Cet article parlera du problème de pointage de ceci dans vue2.x et expliquera pourquoi cela pointe vers l'instance de vue. J'espère que cela sera utile à tout le monde !
Dans la présentation du code au sein du groupe, j'ai accidentellement mentionné pourquoi cela peut être directement appelé aux valeurs des données, des méthodes, des accessoires et calculé. Ensuite, tout le monde a eu des suppositions, mais il n'y avait pas de réponse claire. Pour clarifier ce problème, consultez Après avoir compris le code source de vue, j'écrirai un article pour l'enregistrer.
Posez une question
Développez normalement du code vue, écrivez-le presque toujours comme ça
export default { data() { return { name: '彭鱼宴' } }, methods: { greet() { console.log(`hello, 我是${this.name}`) } } }
Pourquoi this.name ici peut-il accéder directement au nom défini dans data, ou this.someFn peut accéder directement aux méthodes Quant à la fonction définie , avec cette question à l'esprit, j'ai commencé à regarder le code source de vue2.x pour trouver la réponse.
Analyse du code source
Voici l'adresse du code source de vuecode source vue. Jetons d'abord un coup d'œil au constructeur de l'instance vue. Le constructeur se trouve dans le répertoire du code source /vue/src/core/instance/index.js. Postez tout cela et voyez. Le constructeur est très simple, if (!(cette instance de Vue)){}
Déterminez si le mot-clé new
est utilisé pour appeler le constructeur. Sinon, un avertissement sera émis. . Voici this</code >Fait référence à une instance de Vue. Si le mot clé <code>new
est utilisé normalement, utilisez simplement la fonction _init
. N'est-ce pas très simple ?
if (!(this instanceof Vue)){}
判断是不是用了 new
关键词调用构造函数,没有则抛出warning,这里的this
指的是Vue的一个实例。如果正常使用了new
关键词,就走_init
函数,是不是很简单。
_init函数分析
function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } this._init(options) } initMixin(Vue) stateMixin(Vue) eventsMixin(Vue) lifecycleMixin(Vue) renderMixin(Vue) export default Vue
_init函数有点长,做了很多事情,这里就不一一解读,和我们此次探索相关的内容应该在initState(vm)这个函数中,我们继续到initState这个函数里看看。
initState函数分析
let uid = 0 export function initMixin (Vue: Class<Component>) { Vue.prototype._init = function (options?: Object) { const vm: Component = this // a uid vm._uid = uid++ let startTag, endTag /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { startTag = `vue-perf-start:${vm._uid}` endTag = `vue-perf-end:${vm._uid}` mark(startTag) } // a flag to avoid this being observed vm._isVue = true // 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 ) } /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { initProxy(vm) } else { vm._renderProxy = vm } // expose real self vm._self = vm initLifecycle(vm) initEvents(vm) initRender(vm) callHook(vm, 'beforeCreate') initInjections(vm) // resolve injections before data/props initState(vm) initProvide(vm) // resolve provide after data/props callHook(vm, 'created') /* istanbul ignore if */ if (process.env.NODE_ENV !== 'production' && config.performance && mark) { vm._name = formatComponentName(vm, false) mark(endTag) measure(`vue ${vm._name} init`, startTag, endTag) } if (vm.$options.el) { vm.$mount(vm.$options.el) } } }
可以看出initState做了5件事情
- 初始化props
- 初始化methods
- 初始化data
- 初始化computed
- 初始化watch
我们先重点看看初始化methods做了什么
initMethods 初始化方法
export function initState (vm: Component) { vm._watchers = [] const opts = vm.$options if (opts.props) initProps(vm, opts.props) if (opts.methods) initMethods(vm, opts.methods) if (opts.data) { initData(vm) } else { observe(vm._data = {}, true /* asRootData */) } if (opts.computed) initComputed(vm, opts.computed) if (opts.watch && opts.watch !== nativeWatch) { initWatch(vm, opts.watch) } }
initMethods主要是一些判断:
function initMethods (vm, methods) { var props = vm.$options.props; for (var key in methods) { { if (typeof methods[key] !== 'function') { warn( "Method \"" + key + "\" has type \"" + (typeof methods[key]) + "\" in the component definition. " + "Did you reference the function correctly?", vm ); } if (props && hasOwn(props, key)) { warn( ("Method \"" + key + "\" has already been defined as a prop."), vm ); } if ((key in vm) && isReserved(key)) { warn( "Method \"" + key + "\" conflicts with an existing Vue instance method. " + "Avoid defining component methods that start with _ or $." ); } } vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm); } }
除去上述说的这些判断,最重要的就是在vue实例上定义了一遍methods里所有的方法,并且使用bind函数将函数的this指向Vue实例上,就是我们new Vue()的实例对象上。
这就解释了为啥this可以直接访问到methods里的方法。
initData 初始化数据
判断methods中定义的函数是不是函数,不是函数就抛warning; 判断methods中定义的函数名是否与props冲突,冲突抛warning; 判断methods中定义的函数名是否与已经定义在Vue实例上的函数相冲突,冲突的话就建议开发者用_或者$开头命名;
initdata做了哪些事情呢:
- 先在实例 _data 上赋值,getData函数处理 data 这个 function,返回的是一个对象
- 判断最终获取到的 data, 不是对象给出警告。
- 判断methods里的函数和data里的key是否有冲突
- 判断props和data里的key是否有冲突
- 判断是不是内部私有的保留属性,若不是就做一层代理,代理到 _data 上
- 最后监听data,使之成为响应式数据
再看下proxy函数做了什么:
function initData (vm) { var data = vm.$options.data; data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {}; if (!isPlainObject(data)) { data = {}; warn( 'data functions should return an object:\n' + 'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function', vm ); } // proxy data on instance var keys = Object.keys(data); var props = vm.$options.props; var methods = vm.$options.methods; var i = keys.length; while (i--) { var key = keys[i]; { if (methods && hasOwn(methods, key)) { warn( ("Method \"" + key + "\" has already been defined as a data property."), vm ); } } if (props && hasOwn(props, key)) { warn( "The data property \"" + key + "\" is already declared as a prop. " + "Use prop default value instead.", vm ); } else if (!isReserved(key)) { proxy(vm, "_data", key); } } // observe data observe(data, true /* asRootData */); }
其实这里的Object.defineProperty
就是用来定义对象的
proxy
的用处就是使this.name
指向this._data.name
剩下的observe函数不在此次探讨范围,感兴趣的朋友可以自己去看看源码。
总结
回到一开始抛出的问题做一个解答:
methods
里的方法通过bind
指定了this
为 new Vue的实例(vm
),methods里的函数也都定义在vm
上了,所以可以直接通过this
直接访问到methods
里面的函数。data
函数返回的数据对象也都存储在了new Vue的实例(vm
)上的_data
上了,访问this.name
时实际访问的是Object.defineProperty
代理后的this._data.name
Analyse de la fonction _init- Initialiser les accessoires🎜
- Initialisation méthodes🎜
- Initialiser les données🎜
- Initialiser calculé🎜
- Initialiser la montre🎜🎜🎜Concentrons-nous d'abord sur ce que font les méthodes d'initialisation🎜🎜🎜initMethods Méthodes d'initialisation🎜🎜rrreee🎜initMethods sont principalement des jugements :🎜rrreee 🎜Sauf pour les jugements ci-dessus, 🎜la chose la plus importante est de définir toutes les méthodes dans les méthodes sur l'instance de vue et d'utiliser la fonction bind pour pointer le this de la fonction vers l'instance de Vue🎜, qui est l'objet instance de notre nouvelle Vue () . 🎜🎜Cela explique pourquoi cela peut accéder directement aux méthodes dans les méthodes. 🎜🎜🎜initData initialise data🎜🎜rrreee🎜Que fait initdata : 🎜
- Attribuez d'abord une valeur à l'instance _data, la fonction getData traite la fonction de données et renvoie un objet🎜
- Jugement final Le les données obtenues ne sont pas un objet et un avertissement est donné. 🎜
- Déterminez si la fonction dans les méthodes est en conflit avec la clé dans data🎜
- Déterminez s'il y a un conflit entre les accessoires et la clé dans data🎜
- Déterminez s'il s'agit d'un attribut réservé privé interne, sinon, créer une couche Proxy, proxy vers _data🎜
- Enfin, écouter les données et les rendre réactives🎜🎜🎜Regardons ce que fait la fonction proxy :🎜rrreee🎜En fait, le
Object.defineProperty
voici Le but du
🎜🎜proxy
utilisé pour définir des objets est de faire en sorte quethis.name
pointe versthis._data.name
🎜🎜le reste La fonction d'observation n'entre pas dans le cadre de cette discussion. Les amis intéressés peuvent consulter eux-mêmes le code source. 🎜🎜🎜Résumé🎜🎜🎜Reprenez la question posée au début et donnez une réponse : 🎜- La méthode dans 🎜
methods code> Grâce à <code>bind
,this
est spécifié comme l'instance du nouveau Vue (vm
), et les fonctions dans les méthodes sont également définies dansvm
, afin que vous puissiez accéder directement aux fonctions dans lesméthodes
viathis
. 🎜🎜 - 🎜Les objets de données renvoyés par la fonction
data
sont également stockés dans_data
sur la nouvelle instance Vue (vm
), lorsque en accédant àthis.name
, ce qui est réellement accessible estthis._data.name
après le proxyObject.defineProperty
. 🎜🎜🎜🎜Quant aux avantages et aux inconvénients de ce modèle de conception de données, vous pouvez continuer à explorer, après tout, cela ne fait pas partie de cette discussion. 🎜🎜【Recommandation associée : 🎜Tutoriel vidéo vue.js🎜】🎜
- La méthode dans 🎜
function noop (a, b, c) {} var sharedPropertyDefinition = { enumerable: true, configurable: true, get: noop, set: noop }; function proxy (target, sourceKey, key) { sharedPropertyDefinition.get = function proxyGetter () { return this[sourceKey][key] }; sharedPropertyDefinition.set = function proxySetter (val) { this[sourceKey][key] = val; }; Object.defineProperty(target, key, sharedPropertyDefinition); }
Analyse de la fonction initStaterrreee
On peut voir que initState fait 5 choses🎜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!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Un collègue est resté bloqué à cause d'un bug signalé par ce problème de pointage de Vue2 qui a provoqué l'utilisation d'une fonction de flèche, entraînant l'impossibilité d'obtenir les accessoires correspondants. Il ne le savait pas quand je le lui ai présenté, puis j'ai délibérément regardé le groupe de communication front-end. Jusqu'à présent, au moins 70 % des programmeurs front-end ne le comprennent toujours pas. Aujourd'hui, je vais partager avec. vous ce lien. Si tout n'est pas clair Si vous ne l'avez pas encore appris, s'il vous plaît, faites-moi une grande gueule.

Cet article vous aidera à interpréter le code source de Vue et à vous expliquer pourquoi vous pouvez l'utiliser pour accéder aux propriétés de diverses options de Vue2. J'espère qu'il sera utile à tout le monde !

Utilisation flexible du mot-clé this dans jQuery Dans jQuery, le mot-clé this est un concept très important et flexible. Il est utilisé pour désigner l'élément DOM en cours de manipulation. En utilisant rationnellement ce mot-clé, nous pouvons facilement exploiter les éléments de la page et obtenir divers effets et fonctions interactifs. Cet article combinera des exemples de code spécifiques pour présenter l'utilisation flexible de ce mot-clé dans jQuery. Cet exemple simple Tout d'abord, regardons un exemple simple. Supposons que nous ayons un

1. ce mot-clé 1. Type de ceci : L'objet appelé est le type de référence de cet objet 2. Résumé de l'utilisation 1. this.data;//Attribut d'accès 2. this.func();//Méthode d'accès 3.this ( );//Appelez d'autres constructeurs de cette classe 3. Explication de l'utilisation 1.this.data est utilisé dans les méthodes membres. Voyons ce qui se passera si cela n'est pas ajouté classMyDate{publicintyear;publicintmonth;publicintday; intmois,intjour){oui

Qu'est-ce que c'est? L'article suivant vous présentera cela en JavaScript et parlera des différences entre cela dans les différentes méthodes d'appel de fonctions. J'espère que cela vous sera utile !

La fonction flèche en JavaScript est une syntaxe relativement nouvelle. Elle n'a pas son propre mot-clé this. Au contraire, le this de la fonction flèche pointe vers l'objet scope qui la contient. Les impacts sont : 1. Ceci dans la fonction flèche est. static ; 2. Les fonctions fléchées ne peuvent pas être utilisées comme constructeurs ; 3. Les fonctions fléchées ne peuvent pas être utilisées comme méthodes.

1.this référence 1.1 Pourquoi y a-t-il une référence this ? Tout d'abord, écrivons un exemple de classe de date : publicclassclassCode{publicintyear;publicintmonth;publicintday;publicvoidsetDay(inty,intm,intd){year=y;month=m;day= d;}publicvoidprintDate (){System.out.println(année+"-"+mois+"-"+jour);}publicstatic

Comment JavaScript modifie-t-il ce pointeur ? L'article suivant vous présentera trois méthodes pour modifier ce pointeur dans JS. J'espère qu'il vous sera utile !
