vue问题相关记录

1. vue的 nextTick的原理

首先vue实现响应式并不是数据发生变化后dom立即更新,而是按照一定的策略 异步执行dom更新的。
vue在修改数据后,试图不会立即进行更新,而是要等同一事件循环机制内所有数据变化完成之后,在统一更新
nextTick可以让我们在下次dom更新循环结束之后执行延迟回调,用于获取更新后的dom
事件循环机制:
在浏览器中,我们可以将我们的执行任务分为微任务和宏任务
宏任务: 整体javascript,setTimeout,setInterval,setLmmediate
微任务:promise.then promise.all

具体执行顺序:
首先加载js代码,然后在执行里面的同步任务,在执行的过程中如果遇到了异步任务,会把他放到一个任务队列中,在任务队列里面,会判断是宏任务还是微任务,首先会执行宏任务,因为弘任务是整体的javascript代码,所以第一步会先执行宏任务,在执行宏任务的过程中,如果遇到微任务,同样道理,也会把他当到当前的任务队列里面,等这个宏任务执行完毕之后,再去执行当前的微任务,当前微任务执行完毕之后,再去执行下一个宏任务。

<template><div><div>{{ count }}</div><div @click="handleClick">click</div></div>
</template><script>export default {data() {return {count:0}},methods: {handleClick() {for (let i = 0; i < 1000; i++) {this.count++}}},}
</script>

当点击按钮,count会被循环1000次,每次count+1,都会出发count的setter方法,然后修改真实的dom,按此逻辑,真个过程,dom会被更新1000次,而dom的每次更新是非常消耗性能的,而且这样的操作是完全没有必要的,所以vue在内部派发更新时做了优化,也就是并不是每次数据更新,都会去出发回调,而是把更新的数据放到一个任务队列里面,等待所有的数据都更新完毕之后,再去执行回调函数,更新最后的dom

vue.nextTick 原理:
vue中数据变化到dom变化,是一个异步的过程,一旦观察到数据发生变化,vue就会开启一个任务队列,然后把在同一个事件循环中观察的数据变化的Watcher(vue源码中的watcher类是用来更新dep类收集到的依赖的)推送到这个队列中。
如果这个watcher被触发多次,他只会被推送到队列一次,这种缓存行为可以有效的去掉重复数据造成的不必要的计算和dom操作,而到了下一个事件循环时,vue会清空队列,并进行dom更新。nextTick的作用是为了在数据发生变化之后等待vue完成更新dom,可以在数据变化之后立即使用vue。nextTick,js是单线程语言,nextTick的实现就是利用了事件循环的宏任务和微任务。

vue.nextTick的应用:
1.在create生命周期中操作dom
create钩子函数的时候,dom其实并没有进行挂载和渲染,此时是无法操作dom的,我们将操作dom的代码可以方法nextTick只。

<template><div><span ref="text">12345</span></div>
</template><script>
export default {created() {// 会直接报错this.$refs.text.innerHTML = '2222222'this.$nextTick(() => {this.$refs.text.innerHTML = '2222222'})},
}
</script>

2.修改数据获取dom的值
当我们修改了data里的数据时,并不能立即通过操作dom去获取到里面的值,或者说页面的值没有发生变化

<template><div><span ref="text">{{ a }}</span><span>{{ b }}</span><span >{{ c }}</span></div>
</template>
<script>
export default {data() {return {a: 0,b:0,c:0,}},methods: {chage() {this.a = 12// 你会发现获取的值没有发生改变 this.b = this.$refs.text.innerHTMLthis.$emit('check', this.a)//通过加入nextTick后,获取的值才会发生改变,这是在dom更新之后的值this.$nextTick(() => {this.c = this.$refs.text.innerHTML})}},
}
</script>

3.还有一种情况就是在做修改的时候,model对话框没有渲染父组件带过的值

// 通过父组件点击修改或者查看,如果不用nextTick你会发现从父组件带过来的record参数没有被渲染到model对话框上,这个应为visibel为true的时候model还没dom还没有被更新,所以setFieldsValue是不生效的,必须用nextTick异步更新dom之后在去渲染数据edit(record) {this.form.resetFields();this.model = Object.assign({}, record);this.visible = true;this.$nextTick(() => {this.form.setFieldsValue(pick(this.model,"kpilevel","classify",...));});},

2.vue修改数据后页面不重新渲染的问题

在对一个对象遍历之后进行属性添加添加成功之后页面不刷新的问题

<template><div><span v-for="(value, key) in params" :key="key">{{ value }}</span><a-button type="primary" @click="handleClick" icon="search">查询</a-button></div>
</template><script>
export default {data() {return {params: {a: '1',b: 2,c: 3,}}},methods: {handleClick() {this.params.d = 13// 这里能够打印出来,但是页面没有刷新console.log(this.params);}},
}
</script>

问题分析: 应为vue2是用过Object.defineProperty实现数据响应式,组件初始化才递归遍历item,这时候并没有给item的每个属性添加set和get方法,所有后来并没有给newVal设置成响应式数据,结果就是修改后不会视图更新。

const item = {}
Object.defineProperty(obj, 'oldProperty', {get() {console.log(`get oldProperty:${val}`);return val},set(newVal) {if (newVal !== val) {console.log(`set oldProperty:${newVal}`);val = newVal}}
})
}

组件初始化时,对data中的item进行递归遍历,对item的每一个属性进行劫持,添加set,get方法。我们后来新加的newProperty属性,并没有通过Object.defineProperty设置成响应式数据,修改后不会视图更新。

所以vue不允许再以创建的实例上动态的添加新的属性。但是如果想实现数据和试图同步更新,要怎么操作:

1.vue.set( )

target: 需要更改的数据源(可以是一个对象或者数组)
key:需要更改的具体数据,如果是数组元素更改,key表示索引,如果是对象,key表示键值
value:重新赋的值
Vue.set( target, propertyName/index, value )this.$set(this.params, "newProperty", "新值");
this.$set(this.params, 13, {key: 'newkey', name: '888'})

2. Object.assign( )

this.params = Object.assign({},this.params,{newProperty:'新值'})

3. $forceUpdate( )
这种迫使vue强制刷新,迫使dom重新渲染,他会影响本身,还有涉及到的子组件以及插槽,都会更新,一般是不建议使用

this.params.newProperty = "新值" 
this.$forceUpdate();

4. 通过扩展语法 …

  const aa = { ...this.params, d: 13 }this.params = aa

5.同过在组件添加一个key,对key来进行修改

  <span :key="componentKey" /><span v-for="(value, key) in params" :key="key">{{ value }}</span><a-button type="primary" @click="handleClick" icon="search">查询</a-button>handleClick() {this.params.d = 13this.componentKey += 1}

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

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

相关文章

使用代理突破浏览器IP限制

一、实验目的: 主要时了解代理服务器的概念&#xff0c;同时如何突破浏览器IP限制 二、预备知识&#xff1a; 代理服务器英文全称是Proxy Server&#xff0c;其功能就是代理网络用户去取得网络信息。形象的说&#xff1a;它是网络信息的中转站&#xff0c;特别是它具有一个cac…

通过终端命令实现本地文件与远程Git仓库的上传与拉取!

上传 要将本地文件上传到Git仓库&#xff0c;需要遵循以下步骤&#xff1a; 1. **初始化仓库&#xff08;如果尚未初始化&#xff09;&#xff1a;** 导航到包含你的项目文件的文件夹&#xff0c;打开命令行(windows)或终端(git) git终端下载&#xff1a;Git的下载与安装教…

【Unity学习笔记】DOTween(1)基础介绍

本文中大部分内容学习来自DOTween官方文档 文章目录 什么是DOTween&#xff1f;DOSetOnTweenerSequenceTweenNested tween 初始化使用方式 什么是DOTween&#xff1f; DOTween是一个动画插件&#xff0c;Tween是补间的意思。这个插件以下简称DOT&#xff0c;DOT很方便使用&…

浅谈容器网络

1.什么是容器网络 容器网络是一种新兴的应用程序沙箱机制&#xff0c;用于家庭桌面和网络规模的 企业网络 解决方案&#xff0c;其概念与虚拟机类似。容器内部与主机和所有其他容器隔离的是一个功能齐全的 Linux 环境&#xff0c;具有自己的用户、文件系统、进程和网络堆栈。容…

标题:探索对称二叉树的奥秘

二叉树 题目连接 在计算机科学领域&#xff0c;二叉树是一种常见的数据结构&#xff0c;其灵活性和广泛的应用使得研究不断深入。其中&#xff0c;LeetCode 题目 "101. 对称二叉树" 提供了一个非常有趣且具有挑战性的问题&#xff0c;涉及到二叉树的对称性判断。通…

汽车制造业外发文件时 如何阻断泄密风险?

汽车制造业是我国国民经济发展的支柱产业之一&#xff0c;具有产业链长、关联度高、就业面广、消费拉动大等特性。汽车制造行业景气度与宏观经济、居民收入水平和固定资产投资密切相关。 汽车制造业产业链长&#xff0c;关联度高&#xff0c;汽车制造上游行业主要为钢铁、化工…

https 的ssl证书过期处理解决方案(lighthttpd)

更换证书&#xff1a;lighthttpd 配置文件位置&#xff1a;/opt/vmware/etc/lighttpd/lighttpd.conf &#xff08;配置文件的最底部 G快速来到底部&#xff09; 方案一&#xff1a;阿里云申请免费的证书 这里公司内网环境没有配置域名&#xff0c;可以创建一个临时域名&…

MySQL 触发器

目录 一、触发器概述 二、触发器操作 1、创建触发器 2、查看触发器 3、删除触发器 三、触发器应用 一、触发器概述 MySQL的触发器和存储过程一样&#xff0c;都是嵌入到MySQL的一段程序。触发器是由时间来触发某个操作&#xff0c;这些时间包括INSERT、UPDATE和DELETE语…

IDEA启动Tomcat两个端口的方式 使用nginx进行反向代理 JMeter测试分布式情况下synchronized锁失效

目录 引出IDEA启动Tomcat两个端口的方式1.编辑配置2.添加新的端口-Dserver.port80833.service里面管理4.启动后进行测试 使用nginx进行反向代理反向代理多个端口运行日志查看启动关闭重启 分布式情况下synchronized失效synchronized锁代码启动tomcat两个端口nginx反向代理JMete…

木叶飞舞之【机器人ROS2】篇章_第二节、turtlebot3安装

没有真实小车的情况下&#xff0c;利用gazebo的仿真&#xff0c;操作小乌龟来学习ros2。废话不多说&#xff0c;直接上命令。 Install Gazebo sudo apt install ros-humble-gazebo-*Install Cartographer 假如前一节未安装源码版本的cartographer&#xff0c;那就安装apt版本…

5.8 汇编语言:汇编高效除法运算

通常情况下计算除法会使用div/idiv这两条指令&#xff0c;该指令分别用于计算无符号和有符号除法运算&#xff0c;但除法运算所需要耗费的时间非常多&#xff0c;大概需要比乘法运算多消耗10倍的CPU时钟&#xff0c;在Debug模式下&#xff0c;除法运算不会被优化&#xff0c;但…

uniapp 实现切换tab锚点定位到指定位置

1.主要使用uniapp scroll-view 组件的scroll-into-view属性实现功能 2.代码如下 <scroll-view:scroll-into-view"intoView"><u-tabsclass"tabs-list"change"tabChange":list"tabList"></u-tabs><view id"1&…

macOS - 安装 Python 及地址

文章目录 Python 官方安装包Pip3Applications - PythonMiniconda多个python环境有多种方式安装 python,比如 Python 官方包、anaconda、miniconda、brew 等 这里记录使用 Python 官方包进行安装,和 miniconda 安装方式,以及安装后 各执行文件、安装包的地址。 明确这些地址后…

Ceph入门到精通-大流量10GB/s LVS+OSPF 高性能架构

LVS 和 LVSkeepalived 这两种架构在平时听得多了&#xff0c;最近才接触到另外一个架构LVSOSPF。这个架构实际上是LVSKeepalived 的升级版本&#xff0c;我们所知道LVSKeepalived 架构是这样子的&#xff1a; 随着业务的扩展&#xff0c;我们可以对web服务器做水平扩展&#xf…

Redis工具类(缓存操作,Object转换成JSON数据)

依赖spring-data-redis-2.4.1.jar Component Data public class RedisUtils {Autowiredprivate RedisTemplate<String, Object> redisTemplate;Resource(name "stringRedisTemplate")private ValueOperations<String, String> valueOperations;/*** 默…

有线耳机插入电脑没声音

有线耳机插入电脑没声音 首先确保耳机和电脑都没问题&#xff0c;那就有可能是声音输出设备设置错误 右击任务栏的声音图标-打开声音设置-选择输出设备。

MySQL回表是什么?哪些情况下会回表

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责…

一个滚动框高度动态计算解决方案

需求描述&#xff0c;一个嵌套了很多层div或者其他标签的内容框&#xff0c;而它的外层没有设置高度&#xff0c;或者使用百分比&#xff0c;而本容器需要设置高度来实现滚动&#xff0c;要么写死px高度&#xff0c;但是不能自适应&#xff0c;此时需要一个直系父容器&#xff…

iview时间控件 动态不可选日期 可选择24小时范围内 时间往后退24小时

演示 html 设定 起始时间 触发on-change 方法结束时间 options 动态设置不可选择的日期。 <!-- 起始时间 --> <FormItem :label"$t(startTime)" prop"startTime"><DatePickertransfertype"datetime":placeholder"$t(pleas…

php 系列题目,包含查看后端源代码

一、弱类型比较问题 原则&#xff1a; 1.字符串和数字比较&#xff0c;字符串回被转换成数字。 "admin" 0&#xff08;true) admin被转换成数字&#xff0c;由于admin是字符串&#xff0c;转换失败&#xff0c;变成0 int(admin)0,所以比较结果是ture 2.混合字符串转…