一、如何禁止对象属性的改变
通过set对对象的属性更改进行劫持,当对对象的属性进行改变的时候,提示警告。
const dataDef = {}
dataDef.get = function () { return this._data }
const propsDef = {}
propsDef.get = function () { return this._props }
if (process.env.NODE_ENV !== 'production') {
// 禁止对Vue.prototype.$data属性的更改
dataDef.set = function () {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
)
}
// 禁止对Vue.prototype.$props属性的更改
propsDef.set = function () {
warn(`$props is readonly.`, this)
}
}
Object.defineProperty(Vue.prototype, '$data', dataDef)
Object.defineProperty(Vue.prototype, '$props', propsDef)
二、Vue是如何实现原型(实例)属性和静态属性的
Vue的构造函数非常简单,其实就一行代码,如下
function Vue (options) {
this._init(options)
}
- Vue的实例属性
- Vue的静态属性
- Vue的实例属性和Vue的静态属性的最大区别是静态属性中是没办法获取Vue的实例vm(其实就是this) 比如:
function VTest() {
this.a = 1
}
VTest.prototype.$Set = function() {
console.log('prototype',this.a);
//可以打印出1
} //原型属性
VTest.Set = function() {
console.log('VTest', this.a);
//打印不出1
} //静态属性
let VTestObj = new VTest()
VTestObj.$Set(); //会被实例化,类似于Vue实例的实例属性
VTest.Set(); //不会被实例化,其实就是Vue提供的全局API
三、Vue.use的作用
主要功能是封装自定义的原型属性比如Vue.prototype.$Toas或者全局注册组件Vue.component的功能,方便使用者,比如我们用element-ui的时候Vue.use(ElementUI);
- 源码其实很简单
//源码
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) { //Vue.use实现,支持函数或者对象
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))//防止重复注册
if (installedPlugins.indexOf(plugin) > -1) { //如果已经注册,返回
return this
}
// additional parameters
const args = toArray(arguments, 1)
args.unshift(this) //this其实就是Vue
if (typeof plugin.install === 'function') { //函数的情景
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
plugin.apply(null, args)
}
installedPlugins.push(plugin)
return this
}
}
- 如何用
含有install方法的对象
const LlsAlert = {}
LlsAlert.install = (Vue, options) => {
Vue.prototype.$LlsAlert = (msg) => {
alert(msg)
}
}
Vue.use(Toast);
//单独注册Alert组件
import Alert from './src/main';
Alert.install = function(Vue) {
Vue.component(Alert.name, Alert);
};
export default Alert;
四、如何创建一个原型不是Object的对象
Vue中对象的初始化很多使用了Object.create(null)语句,这种方式创建的对象,其原型为null,对象更纯净些