一、$i18n是如何挂载到vue.prototype上面的

- main.js中执行
import i18n from './lang'
- lang/index.js 中执行
Vue.use(VueI18n)
vue.use()
触发的就是 install()
方法, 用来注册插件。
- 开始执行
vue-i18n
源码中的install()
方法。
extend(Vue)
Vue.mixin(mixin)
-
执行extend()
-
执行extend中的以下代码
Object.defineProperty(Vue.prototype, '$i18n', {
get () { return this._i18n }
})
注意:
-
this
代表vue.prototype
在 get 和 set 方法中,this 指向某个被访问和修改属性的对象。 - 这里首次,
this._i18n
是没有值的, 但是Object.defineProperty()
可以监听属性的变化(赋值会触发getter、setter)。
实际要到步骤 6 才会真正有值
- 执行Vue.mixin(mixin)
在 mixin 中开始对this._i18n
赋值
beforeCreate: function beforeCreate () {
var options = this.$options;
options.i18n = options.i18n || (options.__i18n ? {} : null);
if (options.i18n) {
} else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) {
// root i18n 根vue实例
this._i18n = this.$root.$i18n;
this._i18n.subscribeDataChanging(this);
this._subscribing = true;
} else if (options.parent && options.parent.$i18n && options.parent.$i18n instanceof VueI18n) {
// parent i18n 父实例
this._i18n = options.parent.$i18n;
this._i18n.subscribeDataChanging(this);
this._subscribing = true;
}
}
上述 mixin 的beforeCreate
方法中, 以 this.$options
为判断条件,在首次进入mixin中的时候,i18n
是不存在的,为什么呢??
- 因为
Vue.mixin()
是全局注册混入对象,影响之后创建的所有 vue 实例 - 在创建 vue 实例时,并没有在选项中包含自定义属性
i18n
或者__i18n
, 所以在this.$options
中是不存在属性i18n
的。
但是在根 vue 实例 this.$root
中是有 i18n
的,因为在 main.js 中, 创建根 vue 实例时,是下面这样的 :
new Vue({
el: '#app',
router,
store,
i18n, // 我在这里
render: h => h(App)
})
所以通过 this.$root.$i18n
给 this.$i18n
赋值, 而这个赋值操作,又会触发 Object.defineProperty()
中的 get 方法,此时才真正的将 $i18n
挂载到 vue.prototype
上面。
二、动态切换语言选项后,vue-i18n是怎么起作用的?
vue-i18n切换语言选项时,在应用层面,只需要知道以下一行代码即可。
// 当前的语言
this.$i18n.locale = lang
那么底层在接收到最新的语言选项之后,是如何作用在页面上的呢???
在类 VueI18n
中,有以下方法 watchLocale()
,用来监听 locale
的变化。具体操作,看注释即可。
watchLocale (): ?Function {
/* istanbul ignore if */
if (!this._sync || !this._root) { return null }
const target: any = this._vm // vue 实例
return this._root.$i18n.vm.$watch('locale', (val) => {
// 重新对 locale 赋值
target.$set(target, 'locale', val)
// 迫使 Vue 实例重新渲染
target.$forceUpdate()
}, { immediate: true })
}
网友评论