面试只是起点,能力才是终局
目的: 将图形界面开发与业务逻辑解耦。
模型(Modal):模型是☞代表真实状态内容的模型。
视图(View): 就是用户界面。
视图模型(ViewModal): 是暴露的公共属性和命令的抽象。
只有当实例创建时已经存在data中的属性才是响应式的。如果用vm.b = 'test'
,那么修改这个值将没有任何作用。
实例创建的时候需要一系列的初始化过程,设置数据监听/编译模板/挂载Dom/数据变化时更新Dom等。这个过程中会执行生命周期函数。
这图应该好好看一下,比较全面的描述了Vue加载的过程。
new Vue()
创建实例---> 初始化事件、生命周期 ---> 执行beforeCreated ---> 初始化响应式方法 ---> 执行created ---> 判断是否有el option
---> 是否有 template option
---> 执行beforeMount ---> 创建实例的el ---> 执行mounted ---> 挂载完成 ---> 数据更新 ---> 执行beforeUpdate ---> 重新渲染虚拟Dom / 触发patch ---> 执行update ---> 销毁组件 ---> 执行vm.$destory() ---> beforeDestroy ---> 销毁watcher,子组件,及事件监听 ---> 销毁完成。
模板内的表达式非常便利。但是初衷是用于简单运算。逻辑过重则难以维护,对于复杂逻辑则应当使用计算属性
。
计算属性基于响应式依赖进行缓存。只在响应式依赖发生改变时才会重新求值。
计算属性默认只有getter属性,也可以在需要时设置setter方法。
当数据需要在数据变化时执行异步或开销比较大的操作时,使用watch 侦听属性。
暂无
带有 v-show 的元素会一直保留在Dom中,v-show只是切换css的display属性。
v-if 只有在条件为true时展示元素。
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。
当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态
(例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
import { def } from '../util/index'
const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
/**
* Intercept mutating methods and emit events
*/
methodsToPatch.forEach(function (method) {
// cache original 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
})
})
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
这些方法都是在实例初始化的过程当中挂载到实例的prototype属性上的。
Vue.prototype.$emit = function (event: string): Component {
const vm: Component = this
if (process.env.NODE_ENV !== 'production') {
const lowerCaseEvent = event.toLowerCase()
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
`Event "${lowerCaseEvent}" is emitted in component ` +
`${formatComponentName(vm)} but the handler is registered for "${event}". ` +
`Note that HTML attributes are case-insensitive and you cannot use ` +
`v-on to listen to camelCase events when using in-DOM templates. ` +
`You should probably use "${hyphenate(event)}" instead of "${event}".`
)
}
}
let cbs = vm._events[event]
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs
const args = toArray(arguments, 1)
const info = `event handler for "${event}"`
for (let i = 0, l = cbs.length; i < l; i++) {
invokeWithErrorHandling(cbs[i], vm, args, vm, info)
}
}
return vm
}
我们一直认为vue-router中 hash模式
的核心是hashChange
事件。但其实除了hashChange事件外,还有一个popstate事件。
当活动历史记录条目更改时,将触发popstate
事件。如果被激活的历史记录条目是通过对history.pushState()
的调用创建的,或者受到对history.replaceState()
的调用的影响,popstate事件的state属性包含历史条目的状态对象的副本。
需要注意的是调用history.pushState()
或history.replaceState()
不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件
,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back()或者history.forward()方法)。
不同的浏览器在加载页面时处理popstate事件的形式存在差异。页面加载时Chrome和Safari通常会触发(emit )popstate事件,但Firefox则不会。
本文分享自 JavaScript高级程序设计 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!