Vue深入学习4—指令和生命周期

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.生命周期

image-20210725222206025

  • 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>
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')

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/651650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

原创改进 | 融合蝠鲼觅食与联想学习的量子多目标灰狼优化算法(Matlab)

​前面的文章里作者介绍了多目标灰狼优化算法(Multi-Objective Grey Wolf Optimizer&#xff0c;MOGWO)&#xff0c;该算法是由Mirjalili等(灰狼算法的提出者)于2016年提出[1]&#xff0c;发表在中科院一区期刊《expert systems with applications》。 MOGWO保留了灰狼算法的种…

使用Excel计算--任务完成总工作日时间段

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu) 引言 计算任务完成时间周期&#xff0c;和计算金钱一样&#xff0c;是一个比较细致严谨的工作。 通常&#xff0c;我们可能以为&#xff0c;完成周期形如&#xff1a; 任务完成周期 任务结束时间 - 任务开始时间 但是…

Lambda常用表达式

Lambda常用表达式 在Java中&#xff0c;Lambda表达式和Stream API是一起使用的常用组合。下面是一些常见的Lambda表达式和Stream方法的用法示例&#xff1a; 1. 使用Lambda表达式创建一个Runnable对象&#xff1a; Runnable r () -> System.out.println("Hello, Lamb…

在 Ubuntu 上安装 Docker Engine

系列文章目录 前言 要在 Ubuntu 上开始使用 Docker Engine&#xff0c;请确保满足先决条件&#xff0c;然后按照安装步骤进行操作。 一、先决条件 注意事项 如果您使用 ufw 或 firewalld 管理防火墙设置&#xff0c;请注意当您使用 Docker 暴露容器端口时&#xff0c;这些端口…

AndroidStudio安装教程基础篇

Android Studio是专为Android应用程序开发而设计的官方集成开发环境&#xff08;IDE&#xff09;。它提供了丰富的工具和功能&#xff0c;帮助开发者更高效地构建出色的应用程序。本文将为您提供Android Studio的安装文档基础指南&#xff0c;帮助您顺利安装并开始使用这款强大…

时序数据库Tdengine 批量插入避免因为主键ts时间重复导致数据被覆盖掉

目录 在Mybatis中使用 在数据库管理工具中使用 now100a 使用now() #{index}a 其中那这个 #{index}是<foreach>标签里的循环出来的index 在Mybatis中使用 <insert id"batchInsert" parameterType"java.util.List">insert into uri(id…

Leetcode 第 111 场双周赛题解

Leetcode 第 111 场双周赛题解 Leetcode 第 111 场双周赛题解题目1&#xff1a;2824. 统计和小于目标的下标对数目思路代码复杂度分析 题目2&#xff1a;2825. 循环增长使字符串子序列等于另一个字符串思路代码复杂度分析 题目3&#xff1a;2826. 将三个组排序思路代码复杂度分…

PCL Kdtree 使用示例

PCL Kdtree 使用示例 文章目录 PCL Kdtree 使用示例一、关于 KDTree二、关于最近邻搜索三、复杂度分析四、C代码示例五、关键函数说明nearestKSearch 函数说明 一、关于 KDTree 点云数据主要是&#xff0c; 表征 目标表面 的海量点集合&#xff0c; 并不具备传统实体网格数据的…

P8651 [蓝桥杯 2017 省 B] 日期问题

#include <iostream> #include <string> using namespace std;int first; int second; int third; int day[13]{0,31,0,31,30,31,30,31,31,30,31,30,31};//每月日期bool select (int i,int j,int k){if ((i%100 first) && (j second) && (k thi…

【美团】SaaS技术部-后端研发工程师(海外业务)

部门介绍 美团餐饮系统为餐饮企业提供一站式IT解决方案&#xff0c;帮助餐饮商户实现从供应链管理、生产管理、前厅管理到外卖的数字化经营。美团餐饮系统不仅打通了餐厅和平台&#xff0c;更帮助餐厅连接客人&#xff0c;让商户更了解顾客需求&#xff0c;在帮助商户做商业决…

分段函数线性化方法matlab测试

目录 1 使用0-1变量将分段函数转换为线性约束 2 连续函数采用分段线性化示例 3 matlab程序测试 4 matlab测试结果说明 5 分段线性化应用 1 使用0-1变量将分段函数转换为线性约束 2 连续函数采用分段线性化示例 3 matlab程序测试 clc;clear all; gn10;tn1; x_pfsdpvar(1, t…

【ArcGIS遇上Python】python实现批量XY坐标生成shp点数据文件

单个手动生成:【ArcGIS风暴】ArcGIS 10.2导入Excel数据X、Y坐标(经纬度、平面坐标),生成Shapefile点数据图层 文章目录 一、问题分析二、解决办法三、注意事项一、问题分析 现有多个excel、txt或者csv格式的坐标数据,需要根据其坐标批量一键生成shp点数据,如下X为经度,…

Java - OpenSSL与国密OpenSSL

文章目录 一、定义 OpenSSL&#xff1a;OpenSSL是一个开放源代码的SSL/TLS协议实现&#xff0c;也是一个功能丰富的加密库&#xff0c;提供了各种主要的加密算法、常用的密钥和证书封装管理功能以及SSL协议。它被广泛应用于Web服务器、电子邮件服务器、VPN等网络应用中&#x…

高考复习技巧考研资料、美赛论文及代码,数据收集网站(初高中招生考试全科试卷等)

图&#xff0c;就要从“点、线、面的位置关系”这一内核开始发散&#xff0c;第一层级为彼此的位置关系&#xff0c;平行、相交、异面&#xff08;两直线间位置&#xff09;、垂直&#xff08;相交或异面中的特殊位置&#xff09;&#xff0c;多面体、旋转体等&#xff0c;然后…

前端实现弹小球功能

这篇文章将会做弹小球游戏&#xff0c;弹小球游戏大家小时候都玩过&#xff0c;玩家需要在小球到达游戏区域底部时候控制砖块去承接小球&#xff0c;并不断的将小球弹出去。 首先看一下实现的效果。 效果演示 玩家需要通过控制鼠标来实现砖块的移动&#xff0c;保证在小球下落…

[C#]de4dot常用命令

命令&#xff1a;de4dot.exe "D:\xxx.exe" 解释&#xff1a;运行后文件在程序集的目录下生成一个带-cleaned的新程序集。 命令&#xff1a;de4dot.exe file1 -f "D:\xxx.exe" -o "D:\output\xxx_cleaned.exe" 解释&#xff1a;-f : 指定.NET 程序…

Maven(下):依赖管理、依赖传递、依赖冲突、工程继承及工程聚合

1. 基于IDEA 进行Maven依赖管理 1.1 依赖管理概念 Maven 依赖管理是 Maven 软件中最重要的功能之一。Maven 的依赖管理能够帮助开发人员自动解决软件包依赖问题&#xff0c;使得开发人员能够轻松地将其他开发人员开发的模块或第三方框架集成到自己的应用程序或模块中&#xf…

Linux 文件和文件夹的创建与删除

目录 一. 新建1.1 mkdir 新建文件夹1.2 touch 新建空文件1.3 vi命令创建文件1.4 > 和 >> 新建文件 二. 删除 一. 新建 1.1 mkdir 新建文件夹 -p&#xff1a;递归的创建文件夹&#xff0c;当父目录不存在的时候&#xff0c;会自动创建 mkdir -p test1/test2/test31.…

MySQL中InnoDB 表的 自增(AUTO_INCREMENT )列详解

innodb表必须将 AUTO_INCREMENT 列定义为某个索引的第一个或唯一列。建议将 AUTO_INCREMENT 列设置为 PRIMARY KEY&#xff08;主键&#xff09;或 UNIQUE&#xff08;唯一键&#xff09;索引的一部分&#xff0c;以防止出现重复值 InnoDB AUTO_INCREMENT 锁模式 InnoDB 使用…

递归神经网络:(01/4) 顺序数据处理的骨干

koushikkushal95 一、说明 循环神经网络是一个里程碑式的模型框架&#xff0c;它是对时间串处理的最基本构架&#xff1b;而理解RNN也是对自然语言处理模型的开端&#xff0c;本篇将对该模型的基本原理进行介绍。 二、顺序数据处理的架构 递归神经网络 &#xff08;RNN&#xf…