一般情况下都放到 mounted 中,保证逻辑的统一性,因为生命周期是同步执行的, ajax 是异步执行的 服务端渲染不支持mounted方法,所以在服务端渲染的情况下统一放到created中 后续文章: 专题二.
1.谈一下你对MVVM原理的理解
据。将结果返回给前端,页面重新渲染
定到 viewModel 层上,会自动将数据渲染到页面中,视图变化会通知 viewModel层 更新数据。
ViewModel 就是我们 MVVM 模式中的桥梁.2.请说一下响应式数据的原理?
理解:
性,当页面取到对应属性时。会进行依赖收集(收集当前组件的watcher) 如果属性发生变化会通
知相关依赖进行更新操作。原理:
Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter() { const value = getter ? getter.call(obj) : val if (Dep.target) { dep.depend() // ** 收集依赖 ** / if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } } return value }, set: function reactiveSetter(newVal) { const value = getter ? getter.call(obj) : val if (newVal === value || (newVal !== newVal && value !== value)) { return } if (process.env.NODE_ENV !== 'production' && customSetter) { customSetter() } val = newVal childOb = !shallow && observe(newVal) dep.notify() /**通知相关依赖进行更新**/ } })
3.Vue中是如何检测数组变化?
理解:
api 时,可以通知依赖更新.如果数组中包含着引用类型。会对数组中的引用类型再次进行监控。原理:
const arrayProto = Array.prototype export const arrayMethods = Object.create(arrayProto) const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ] methodsToPatch.forEach(function (method) { // 重写原型方法 const original = arrayProto[method] // 调用原数组的方法 def(arrayMethods, method, function mutator(...args) { const result = original.apply(this, args) const ob = this.__ob__ let inserted switch (method) { case 'push': case 'unshift': inserted = args break case 'splice': inserted = args.slice(2) break } if (inserted) ob.observeArray(inserted) // notify change ob.dep.notify() // 当调用数组方法后,手动通知视图更新 return result }) }) this.observeArray(value) // 进行深度监控
4.为何Vue采用异步渲染?
理解:
会在本轮数据更新后,再去异步更新视图!原理:
update() { /* istanbul ignore else */ if (this.lazy) { this.dirty = true } else if (this.sync) { this.run() } else { queueWatcher(this); // 当数据发生变化时会将watcher放到一个队列中批量更新 } } export function queueWatcher(watcher: Watcher) { const id = watcher.id // 会对相同的watcher进行过滤 if (has[id] == null) { has[id] = true if (!flushing) { queue.push(watcher) } else { let i = queue.length - 1 while (i > index && queue[i].id > watcher.id) { i-- } queue.splice(i + 1, 0, watcher) } // queue the flush if (!waiting) { waiting = true if (process.env.NODE_ENV !== 'production' && !config.async) { flushSchedulerQueue() return } nextTick(flushSchedulerQueue) // 调用nextTick方法 批量的进行更新 } } }
5.nextTick实现原理?
理解:(宏任务和微任务) 异步方法
nextTick
方法主要是使用了宏任务和微任务,定义了一个异步方法.多次调用 nextTick
会将方法存入
队列中,通过这个异步方法清空当前队列。 所以这个 nextTick
方法就是异步方法原理:
let timerFunc // 会定义一个异步方法 if (typeof Promise !== 'undefined' && isNative(Promise)) { // promise const p = Promise.resolve() timerFunc = () => { p.then(flushCallbacks) if (isIOS) setTimeout(noop) } isUsingMicroTask = true } else if (!isIE && typeof MutationObserver !== 'undefined' && ( // MutationObserver isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]' )) { let counter = 1 const observer = new MutationObserver(flushCallbacks) const textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) } isUsingMicroTask = true } else if (typeof setImmediate !== 'undefined') { // setImmediate timerFunc = () => { setImmediate(flushCallbacks) } } else { timerFunc = () => { // setTimeout setTimeout(flushCallbacks, 0) } } // nextTick实现 export function nextTick(cb?: Function, ctx?: Object) { let _resolve callbacks.push(() => { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true timerFunc() } }
6.Vue中Computed的特点
理解:
原理:
function initComputed(vm: Component, computed: Object) { const watchers = vm._computedWatchers = Object.create(null) const isSSR = isServerRendering() for (const key in computed) { const userDef = computed[key] const getter = typeof userDef === 'function' ? userDef : userDef.get if (!isSSR) { // create internal watcher for the computed property. watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions ) } // component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined // at instantiation here. if (!(key in vm)) { defineComputed(vm, key, userDef) } else if (process.env.NODE_ENV !== 'production') { if (key in vm.$data) { warn(`The computed property "${key}" is already defined in data.`, vm) } else if (vm.$options.props && key in vm.$options.props) { warn(`The computed property "${key}" is already defined as a prop.`, vm) } } } } function createComputedGetter(key) { return function computedGetter() { const watcher = this._computedWatchers && this._computedWatchers[key] if (watcher) { if (watcher.dirty) { // 如果依赖的值没发生变化,就不会重新求值 watcher.evaluate() } if (Dep.target) { watcher.depend() } return watcher.value } } }
7.Watch中的deep:true 是如何实现的
理解:
一项进行求值,此时会将当前 watcher 存入到对应属性的依赖中,这样数组中对象发生变化时也
会通知数据更新原理:
get() { pushTarget(this) // 先将当前依赖放到 Dep.target上 let value const vm = this.vm try { value = this.getter.call(vm, vm) } catch (e) { if (this.user) { handleError(e, vm, `getter for watcher "${this.expression}"`) } else { throw e } } finally { if (this.deep) { // 如果需要深度监控 traverse(value) // 会对对象中的每一项取值,取值时会执行对应的get方法 } popTarget() } return value } function _traverse(val: any, seen: SimpleSet) { let i, keys const isA = Array.isArray(val) if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) { return } if (val.__ob__) { const depId = val.__ob__.dep.id if (seen.has(depId)) { return } seen.add(depId) } if (isA) { i = val.length while (i--) _traverse(val[i], seen) } else { keys = Object.keys(val) i = keys.length while (i--) _traverse(val[keys[i]], seen) } }
8.Vue组件的生命周期
理解:
要掌握每个生命周期什么时候被调用
observer),属性和方法的运算, watch/event 事件回调。这里没有$el
监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。要掌握每个生命周期内部可以做什么事
因为这可能会导致更新无限循环。 该钩子在服务器端渲染期间不被调用。
原理:
9.ajax请求放在哪个生命周期中
理解:
关的元素10.何时需要使用beforeDestroy
理解:
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算