new Vue 发生了什么
1. mergeOptions
合并options
2. initLifecycle(vm)
初始化生命周期
3. initEvents(vm)
初始化事件
4. initRender(vm):初始化render
初始化渲染
5. callHook(vm, 'beforeCreate'):触发 beforeCreate 钩子
触发 beforeCreate 钩子
6. initInjections(vm) // resolve injections before data/props
7. initState(vm):初始化 props、data、computed、methods和watch
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)
}
}
9. initProvide(vm) // resolve provide after data/props
10. callHook(vm, 'created'):触发 created 钩子
触发 created 钩子
init
function Vue(options) {
this._init(options)
}
initMixin(Vue)
function initMixin(Vue) {
Vue.prototype._init = function(options) {
const vm = this
// 一个防止观察自身的标志
vm._isVue = true
vm.$options = options
}
initState(vm)
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
const inBrowser = typeof window !== 'undefined'
Vue.prototype.$mount = function (el, hydrating) {
el = el && inBrowser ? query(el) : undefined
return mountComponent(this, el, hydrating)
}
function mountComponent(vm, el, hydrating) {
vm.$el = el
let updateComponent = () => {
vm._update(vm._render(), hydrating)
}
}
// 缓存之前的$mount
const mount = Vue.prototype.$mount
Vue.prototype.$mount = function(el, hydrating) {
el = el && query(el)
const options = this.$options
if (!options.render) {
let template = options.template
if (template) {
// .
} else {
template = getOuterHTML(el)
}
}
return mount.call(this, el, hydrating)
}
function query (el) {
if (typeof el === 'string') {
const selected = document.querySelector(el)
if (!selected) {
// process.env.NODE_ENV !== 'production' && warn(
// 'Cannot find element: ' + el
// )
return document.createElement('div')
}
return selected
} else {
return el
}
}
function getOuterHTML (el) {
if (el.outerHTML) {
return el.outerHTML
} else {
const container = document.createElement('div')
container.appendChild(el.cloneNode(true))
return container.innerHTML
}
}
function initState(vm) {
const opts = vm.$options
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true)
}
}
function initData(vm) {
let data = vm.$options.data
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {}
const keys = Object.keys(data)
let i = keys.length
while (i--) {
proxy(vm, `_data`, key)
}
observe(data, true /* asRootData */)
}
function getData(data, vm) {
return data.call(vm, vm)
}
const sharedPropertyDefinition = {
enumerable: true,
configurable: true,
get: noop,
set: noop
}
// 等待,无操作
function 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)
}
function observe(value, asRootData) {
}
vdom
用js对象描述真实dom
为什么使用vdom
手动操作dom比较麻烦,还要考虑兼容性问题,虽然有jquery等库简化操作,但随着项目增大,复杂度不断提升
为了简化操作dom,可以使用模板引擎,但是模板引擎没有解决跟踪状态变化的问题,于是vdom出现了
- 开销更小
- 可以合并更改
- 可以跟踪上一次的状态,并且用作
diff
技巧
将事件的创建和销毁写在一起
在 Vue 中,可以用$on和$once去监听所有的生命周期钩子函数,如监听组件的updated钩子函数可以写成this.$on('hook:updated', () => {})
mounted(){
window.addEventListener('resize', xxx)
// 通过hook监听组件销毁钩子函数,并取消监听事件
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', xxx)
})
}
监听子组件的生命周期
需要监听第三方组件数据的变化,但是组件又没有提供change事件
<child @hook:updated="childUpdated" />
前端框架初始化流程及使用技巧
博客介绍了前端框架的初始化流程,包括合并、初始化生命周期、事件、渲染等,还提及触发钩子。说明了使用该框架的原因,是为简化操作、解决跟踪状态变化问题。此外,分享了将事件创建和销毁写在一起、监听子组件生命周期等使用技巧。
193

被折叠的 条评论
为什么被折叠?



