Artikel ini akan membincangkan masalah penunjuk ini dalam vue2.x, dan memperkenalkan sebab ini menunjukkan contoh vue. Saya harap ia akan membantu semua orang.
Laluan kod dalam kumpulan secara tidak sengaja menyebut mengapa ini boleh dipanggil terus ke nilai dalam data, kaedah, prop dan dikira, kemudian semua orang mempunyai beberapa tekaan. tetapi tiada satu pun daripada mereka yang jelas untuk menjelaskan soalan ini, saya menyemak kod sumber vue saya mempunyai sedikit pemahaman dan menulis artikel untuk merekodkannya.
Biasanya bangunkan kod vue, hampir selalu tulis seperti ini
export default { data() { return { name: '彭鱼宴' } }, methods: { greet() { console.log(`hello, 我是${this.name}`) } } }
Mengapa this.name di sini boleh diakses terus ? Bagaimana pula dengan nama yang ditakrifkan dalam data, atau this.someFn boleh terus mengakses fungsi yang ditakrifkan dalam kaedah Dengan memikirkan soalan ini, saya mula melihat kod sumber vue2.x untuk mencari jawapannya.
Berikut ialah alamat kod sumber vue kod sumber vue. Mari kita lihat pada pembina contoh vue Pembina berada dalam direktori kod sumber /vue/src/core/instance/index.js Tidak banyak kod tersebut 🎜>
Struktur ini sangat mudahfunction 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
digunakan untuk memanggil pembina, amaran dilemparkan di sini. Jika kata kunci if (!(this instanceof Vue)){}
digunakan seperti biasa, maka fungsi new
digunakan bukankah ia sangat mudah? this
new
_init
fungsi _init agak panjang dan melakukan banyak perkara, jadi saya tidak akan menerangkannya satu demi satu di sini Kandungan yang berkaitan dengan penerokaan ini harus berada dalam fungsi initState(vm).
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) } } }
Dapat dilihat bahawa initState melakukan 5 perkara
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) } }
Memulakan prop
kaedah permulaan initMethods
initMethods terutamanya beberapa pertimbangan:
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); } }
Kecuali pertimbangan yang dinyatakan di atas,
The perkara yang paling penting ialah untuk mentakrifkan semua kaedah dalam contoh vue, dan gunakan fungsi bind untuk menunjukkan fungsi ini kepada contoh Vue判断methods中定义的函数是不是函数,不是函数就抛warning; 判断methods中定义的函数名是否与props冲突,冲突抛warning; 判断methods中定义的函数名是否与已经定义在Vue实例上的函数相冲突,冲突的话就建议开发者用_或者$开头命名;
Ini menjelaskan mengapa ini boleh terus mengakses kaedah dalam kaedah.
data permulaan initData
Apakah yang dilakukan oleh initdata:
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 */); }
Pertama tetapkan nilai kepada instance_data, fungsi getData Fungsi pemprosesan data mengembalikan objek
Malah,
di sini digunakan untuk mentakrifkan objek Tujuanfunction 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); }
Object.defineProperty
adalah untuk menjadikan
<.>proxy
Fungsi observe bukan dalam skop perbincangan ini kawan-kawan yang berminat boleh menyemak sendiri source code. this.name
this._data.name
), dan fungsi dalam kaedah juga ditakrifkan pada methods
, jadi anda boleh mengakses terus fungsi dalam bind
melalui this
. vm
vm
this
methods
Ia ialah data
selepas proksi. vm
_data
this.name
Object.defineProperty
Mengenai kelebihan dan kekurangan corak reka bentuk data ini, anda boleh terus meneroka, lagipun, ia bukan sebahagian daripada perbincangan ini. this._data.name
Atas ialah kandungan terperinci Mari kita bincangkan tentang masalah penunjuk ini dalam vue2.x Mengapakah ia menunjuk kepada contoh vue?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!