1.Vue是怎么识别 v- 指令的?
首先将HTML结构解析成属性列表,存入到数组中,接着遍历数组中的每一个节点,获取到不同指令对应的方法。

// 将HTML看作真正的属性列表
var ndoeAttrs = node.attributes;
var self = this;
// 类数组对象变为数组,一层一层的遍历节点
[].slice.call(nodeAttes).forEach(attr => {// 这里开始分析指令var attrName = attr.name;var value = attr.value;// 指令都是 v- 开头的var dir = attrName.substring(2);if(attrName.indexOf('v-') == 0){// v-下不同的指令if(dir == 'model'){// console.log('发现了model指令',value);// 添加Watchernew Watcher(self.$vue, value, value => {node.value = value;});// 得到 v 的值var v = self.getVueVal(self.$vue, value);// 显示 v 的值node.value = v;// 添加监听事件,基本实现双向绑定node.addEventListener('input', e => {var newVal = e.target.value;self.setVueVal(self.$vue, value, newVal);v = newVal;});}else if(dir == 'if'){// console.log('发现了if指令',value);}}
})

2.v-model底层是怎么实现的?
v-model 会把关联的相应式数据(info.message),动态的绑定到表单元素的value属性上,让后监听 input 事件;
v-model 绑定的相应数据发生变化时,表单元素的value值也会随之变化。

<template><div><div class="message">{{ info.message }}</div><div><input v-model="info.message" type="text"></div><button @click="change">click</button></div>
</template>
​
<script>export default {data () {return {info: {}}},methods: {change () {this.info.message = 'hello world'}}}
</script>

面试题:v-for 和 v-if为什么不能一起用?

涉及到一个优先级的问题,v-for 比 v-if优先执行,如果一起使用,循环出来的每一项都会去判断一下v-if是否为true或者false,这样就会照成资源的浪费!

3.生命周期

beforeCreate & created
属于实例化阶段,在_init方法内,DOM 被挂载时执行,两个函数都不能获取到 prop、data 中定义的值,也不能调用 methods中定义的函数。

Vue.prototype._init = function (options?: Object) {// ...initLifecycle(vm)initEvents(vm)initRender(vm)callHook(vm, 'beforeCreate')initInjections(vm) // 在prop、data 之前解决注入initState(vm)initProvide(vm) // 解决初始化之后的prop、datacallHook(vm, 'created')// ...
}

beforeMount &mounted
属于挂载阶段,在mountComponent方法内,响应数据被修改时执行,对于同步渲染的子组件而言,mounted 钩子函数的执行顺序是先子后父

export function mountComponent (vm: Component,el: ?Element,hydrating?: boolean
): Component {vm.$el = elcallHook(vm, 'beforeMount')let updateComponentif (process.env.NODE_ENV !== 'production' && config.performance && mark) {updateComponent = () => {const name = vm._nameconst id = vm._uidconst startTag = `vue-perf-start:${id}`const endTag = `vue-perf-end:${id}`
​mark(startTag)const vnode = vm._render()mark(endTag)measure(`vue ${name} render`, startTag, endTag)
​mark(startTag)// 执行vm._update 把 VNode 渲染到 真实 DOM vm._update(vnode, hydrating)mark(endTag)measure(`vue ${name} patch`, startTag, endTag)}} else {updateComponent = () => {vm._update(vm._render(), hydrating)}}// 把它设为vm._watcher 在watcher的构造函数中.// 因为观察者的初始补丁可能会调用$forceUpdate(例如:inside child . exe)// 组件的挂载钩子),依赖于vm._watcher已经定义.new Watcher(vm, updateComponent, noop, {before () {if (vm._isMounted) {callHook(vm, 'beforeUpdate')}}}, true /* isRenderWatcher */)hydrating = false// 手动挂载实例,调用挂载在self上// 挂载在其插入的钩子中为渲染创建的子组件调用if (vm.$vnode == null) {vm._isMounted = truecallHook(vm, 'mounted')}

beforeUpdate & updated
属于更新阶段,在渲染 Watcher 的 before 函数内,元素被销毁之前执行,在 callUpdatedHooks 函数中,等 vm._watcher 的回调执行完毕后,才能执行 update 函数。

export function mountComponent (vm: Component,el: ?Element,hydrating?: boolean
): Component {// ...
​// 把它设为vm._watcher 在watcher的构造函数中.// 因为观察者的初始补丁可能会调用$forceUpdate(例如:inside child . exe)// 组件的挂载钩子),依赖于vm。_watcher已经定义.new Watcher(vm, updateComponent, noop, {before () {if (vm._isMounted) {callHook(vm, 'beforeUpdate')}}}, true /* isRenderWatcher */)// ...
}
​

beforeDestory & destroyed (3.x中更名为 beforeUnmount & unmounted
属于销毁阶段,在 $destroy 函数前执行,从 parent$children 中删掉自身,删除 watcher

Vue.prototype.$destroy = function () {const vm: Component = thisif (vm._isBeingDestroyed) {return}callHook(vm, 'beforeDestroy')vm._isBeingDestroyed = true// 将self从父节点移除const parent = vm.$parentif (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {remove(parent.$children, vm)}// 卸载 watchersif (vm._watcher) {vm._watcher.teardown()}let i = vm._watchers.lengthwhile (i--) {vm._watchers[i].teardown()}// 从数据ob中移除引用// frozen object 没有观察者。if (vm._data.__ob__) {vm._data.__ob__.vmCount--}// 调用最后一个钩子vm._isDestroyed = true// 在当前redered 树上调用销毁钩子vm.__patch__(vm._vnode, null)// 销毁钩子函数callHook(vm, 'destroyed')// 关闭所有实例侦听器。vm.$off()// 删除vue referenceif (vm.$el) {vm.$el.__vue__ = null}// 发布循环引用if (vm.$vnode) {vm.$vnode.parent = null}}

renderTracked & renderTriggered(3.x新增)
都是跟踪虚拟DOM 重新渲染时调用,接收 debugger event 参数;
renderTracked() : 此事件告诉你哪个操作跟踪组件,以及该操作的目标对象和键。
renderTriggered() : 此事件告诉你哪个操作触发重新渲染,以及该操作的目标对象和键。

<div id="app"><button v-on:click="addToCart">Add to cart</button><p>Cart({{ cart }})</p>
</div>
<script>const app = Vue.vreateApp({data(){return{cart: 0}},// cart 操作*跟踪*了 组件renderTracked({ key, target, type }){console.log({ key, target, type })/*{ key: "cart", target:{cart: 0}, type: "get" }*/},// cart 操作*触发*了 重新渲染renderTriggered({ key, target, type }) {console.log({ key, target, type })},methods: {addToCart(){this.cart += 1/*{ key: "cart", target:{cart:1}, type: "set" }*/}}})app.mount('#app')
</script>

总结: Vue生命周期函数就是在初始化,及数据更新过程各个阶段执行不同的钩子函数;在created钩子函数中可以访问到数据,在mounted钩子函数中可以访问到DOM,在destroyed 钩子函数中可以做一些定时器销毁工作!

参考:v-model源码解析

剖析Vue原理&实现双向绑定MVVM

技术胖Vue3知识地图

Vue2与Vue3的生命周期

Vue2和Vue3的区别

Vue深入学习4—指令和生命周期相关推荐

  1. vue实例、指令、生命周期

    vue实例.指令.生命周期 本章重点 1.生命周期 2.插值 3.指令 一.创建一个实例vue实例 每一个vue应用都是通过vue函数创建一个新的vue实例开始的 语法: ver vm = new V ...

  2. [vue] 你有写过自定义指令吗?自定义指令的生命周期(钩子函数)有哪些?

    [vue] 你有写过自定义指令吗?自定义指令的生命周期(钩子函数)有哪些? bind inserted update componentUpdated unbind 个人简介 我是歌谣,欢迎和大家一起 ...

  3. Vue 的属性、方法和生命周期

    实例 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8&qu ...

  4. vue 声明周期函数_Vue2.0 探索之路——生命周期和钩子函数的一些理解

    前言 在使用vue一个多礼拜后,感觉现在还停留在初级阶段,虽然知道怎么和后端做数据交互,但是对于mounted这个挂载还不是很清楚的.放大之,对vue的生命周期不甚了解.只知道简单的使用,而不知道为什 ...

  5. Android学习之碎片的生命周期

    一.碎片的状态: 1.运行状态:当一个碎片是可见的,并且它所关联的活动正处于运行状态时,该碎片也处于运行状态. 2.暂停状态:当一个活动进入暂停状态时(由于另一个未占满屏幕的活动被添加到了栈顶),与它 ...

  6. 微信小程序学习6:页面生命周期回调函数

    微信小程序学习6:页面生命周期回调函数 文章目录 微信小程序学习6:页面生命周期回调函数 1 生命周期图像 2 生命周期回调函数触发条件 onLoad(Object query) onShow() o ...

  7. 【前端学习】React学习笔记-事件、生命周期、虚拟DOMdiffing

    跟着尚硅谷的天禹老师学习React 看视频可以直接点击 b站视频地址 React中的事件处理 补充ref 上面的ref在React官网中提到不要被过度使用,在一些情况下可以使用其他方法来获取数据,比如 ...

  8. Vue —— 基础(六)(生命周期)

    Vue2.x 系列文章目录 内容 参考链接 Vue2.x - 基础(零) 模板语法.数据绑定.el/data写法.MVVM模型 Vue2.x - 基础(一) 数据代理.事件处理.键盘事件 Vue2.x ...

  9. Vue的系列之详解生命周期

    生命周期介绍 简单说就是一个组件从开始到最后消亡所经历的各种状态,就是一个组件的生命周期 vue的生命周期图 beforeCreate(创建前) beforeCreate(初始化页面前) 详情:实例初 ...

最新文章

  1. vscode中使用js的console配置 - mac
  2. Python日志教程
  3. Android 实现无网络传输文件(2)
  4. 推荐一些顶级的开源CI/CD工具
  5. 开发管理 (3) -项目启动会议
  6. (转)Geoserver基础配图研究
  7. Duplicate spring bean id
  8. 汇川,H3U,plc程序模板和触摸屏程序模板,三个步进和三个伺服,三个伺服用的是canlink总线,适用于运动轴控制
  9. 南京大学计算机系住宿环境,请问有没有人知道南京大学计算机系大四学生在哪个校区?...
  10. #数据结构:家谱管理
  11. 转: 多益网络2013校园招聘第二轮笔试题目
  12. 功放限幅保护_【干货】如何利用限幅器保护音箱√
  13. 循环里发送请求java_servlets – 在Java Servlet中转发请求时的无限循环
  14. 【艾兰岛建筑】系列1—五大实用绝招!教你场景建造又快又美!
  15. seu校园网简易自动登陆教程
  16. python数据分析的一般步骤_50. Python 数据处理(1)
  17. 第1.7章 elasticsearch线上问题集1
  18. iOS中GIF图片的加载
  19. nginx搭建图片服务器
  20. 将android studio产生的.gradle .android .androidStudio缓存从默认C盘移动到D盘

热门文章

  1. linux race window,java开发环境(QTrace)
  2. 显示连接失败_技术丨外接显示器障碍的诊断方法
  3. 多目标进化优化(MOEA)方法
  4. API的String 一些用法
  5. MySQL高级之事务
  6. 视频编码技术---压缩感知编码---匹配跟踪算法
  7. 星期三—用JAVA制作简易的通讯软件
  8. poj Balanced Lineup RMQ
  9. macbook装双系统多分区其实很简单,你只要把macbook当作一台普通pc就可以了!
  10. 用VS调试的时候查看指定内存地址