一、new vue时同时写了templet和render函数,优先渲染哪一个?
const vm = new Vue({
el: '#app',
template: '<h1>{{ msg }}</h1>',
render(h) {
return h('h1', this.msg)
},
data: {
msg: 'Hello Vue'
}
})
new vue时,这样写,在有编译器的vue版本下,是先渲染render,入口文件源码如下;
// 把 template/el 转换成 render 函数
if (!options.render) {
let template = options.template
// 如果模板存在
...
}
二、创建vue采用的构造函数而不是class
不用 class 的原因是因为方便后续给 Vue 实例混入实例成员
// 此处不用 class 的原因是因为方便后续给 Vue 实例混入实例成员
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')
}
// 调用 _init() 方法
this._init(options)
}
// 注册 vm 的 _init() 方法,初始化 vm
initMixin(Vue)
// 注册 vm 的 $data/$props/$set/$delete/$watch
stateMixin(Vue)
// 初始化事件相关方法
// $on/$once/$off/$emit
eventsMixin(Vue)
// 初始化生命周期相关的混入方法
// _update/$forceUpdate/$destroy
lifecycleMixin(Vue)
// 混入 render
// $nextTick/_render
renderMixin(Vue)
三、注册 Vue.use() 用来注册插件
export function initUse (Vue: GlobalAPI) {
Vue.use = function (plugin: Function | Object) {
//installedPlugins数组来存储已经注册了的插件
const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
//如果插件已经注册,直接返回
if (installedPlugins.indexOf(plugin) > -1) {
return this
}
// additional parameters
// 把数组中的第一个元素(plugin)去除
const args = toArray(arguments, 1)
// 把this(Vue)插入第一个元素的位置
args.unshift(this)
//传入的插件是对象,调用他的install方法直接注册
if (typeof plugin.install === 'function') {
//在plugin下传入args参数执行
plugin.install.apply(plugin, args)
} else if (typeof plugin === 'function') {
//如果传入的插件是函数,直接调用函数注册
plugin.apply(null, args)
}
//最后将插件放入已经注册好的列表里
installedPlugins.push(plugin)
return this
}
}
四、Vue.minx实现
export function initMixin (Vue: GlobalAPI) {
Vue.mixin = function (mixin: Object) {
//把mixin的成员全部拷贝到vue.options中
this.options = mergeOptions(this.options, mixin)
return this
}
}
五、Provide / Inject使用
provide/inject用于父子组件传参;
我们也可以在组合式 API 中使用 provide/inject。两者都只能在当前活动实例的 setup() 期间调用;
父组件provide,子组件接收inject
为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide 值时使用 ref 或 reactive
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
provide('location', location)
provide('geolocation', geolocation)
}
六、谈一下你对MVVM原理的理解
传统的 MVC 指的是,用户操作会请求服务端路由,路由会调用对应的控制器来处理,控制器会获取数
据。将结果返回给前端,页面重新渲染
MVVM :传统的前端会将数据手动渲染到页面上, MVVM 模式不需要用户收到操作 dom 元素,将数据绑
定到 viewModel 层上,会自动将数据渲染到页面中,视图变化会通知 viewModel层 更新数据。
ViewModel 就是我们 MVVM 模式中的桥梁.
七、 请说一下响应式数据的原理?
理解:
1.核心点: Object.defineProperty
2.默认 Vue 在初始化数据时,会给 data 中的属性使用 Object.defineProperty 重新定义所有属
性,当页面取到对应属性时。会进行依赖收集(收集当前组件的watcher)
如果属性发生变化会通
知相关依赖进行更新操作。
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
// 如果预定义的 getter 存在则 value 等于getter 调用的返回值
// 否则直接赋予属性值
const value = getter ? getter.call(obj) : val
// 如果存在当前依赖目标,即 watcher 对象,则建立依赖
if (Dep.target) {
dep.depend()
// 如果子观察目标存在,建立子对象的依赖关系
if (childOb) {
childOb.dep.depend()
// 如果属性是数组,则特殊处理收集数组对象依赖
if (Array.isArray(value)) {
dependArray(value)
}
}
}
// 返回属性值
return value
}