路由模式(2种) Vue.nextTick 的原理和用途

路由模式(2种)

在vue-router路由对象中,路由有两种模式:hash和history,而默认的是hash模式.

hash路由
onhashchange事件,可以在windows对象上监听这个事件:

windows.onhashchange = function(event){
  console.log(event.oldURL,event.newURL);
let hash = location.hasg  //通过location对象来获取hash地址
console.log(hash)  // #/notebooks/123456/list  地址从#号开始
}

因为hash发生变化的url都会被浏览器记录下来,从而会发现浏览器的前进后退都可以用

history路由
随着 history api的到来,前端路由开始进化了,前面的hashchange,你只能改变#后面的url片段,而history api则给了前端完全的自由,history api可以分为两大部分,切换和修改
切换历史状态
包括 back,forward,go三个方法,对应浏览器的前进,后退,跳转操作。很多小伙伴只知道浏览器有前进和后退,其实在前进后退上长按鼠标,会弹出历史记录,从而完成跳转.

history.go(-2); //后退两次
history.go(2);//前进两次
history.back();//后退
history.forward();前进

修改历史状态
包括了pushState,replaceState两个方法,这两个方法接受三个参数:stateObj,title,url

history.pushState({color:'red','red','red'})
history.back();

通过pushstate把页面的状态保存在state对象中,当页面的url再变回这个url时,可以通过event.state取到这个state对象.
history 模式的补充
对于vue开发的单页面应用,我们在切换不同的页面的时候,可以发现html永远只有一个,这也真是称之为单页面的原因,而vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。而当开启history模式的时候,如果后端不进行任何处理,在Dev阶段一切都是正常的,可是打包之后,访问路径则会返回404,因此要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是app 依赖的页面。

Vue.nextTick 的原理和用途

JS 运行机制
JS 执行是单线程的,它是基于事件循环的。事件循环大致分为以下几个步骤:

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件(根据放置先后时间顺序决定事件执行顺序)。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。

<img src="../assets/event-loop.png"/>

主线程的执行过程就是一个 tick,而所有的异步结果都是通过 “任务队列” 来调度被调度。 消息队列中存放的是一个个的任务(task)。 规范中规定 task 分为两大类,分别是 macro task 和 micro task,并且每个 macro task 结束后,都要清空所有的 micro task。

关于 macro task 和 micro task 的概念,这里不会细讲,简单通过一段代码演示他们的执行顺序:

在这里插入图片描述

在浏览器环境中,常见的 macro task 有 setTimeout、MessageChannel、postMessage、setImmediate;常见的 micro task 有 MutationObsever 和 Promise.then。

Vue.nextTick(callback) 使用原理:
原因是,Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOm操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。
当你设置 vm.someData = ‘new value’,DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
定义:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

所以就衍生出了这个获取更新后的DOM的Vue方法。所以放在Vue.nextTick()回调函数中的执行的应该是会对DOM进行操作的 js代码;

理解:nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数,

nextTick属于微任务

同步代码执行 -> 查找异步队列,推入执行栈,执行Vue.nextTick[事件循环1] ->查找异步队列,推入执行栈,执行Vue.nextTick[事件循环2]

在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM,示例如下:

<template>
<div class="nextTick">
	<div ref="msgDiv">{{msg}}</div>
	<button @click="changeMsg">
		Change the Message
	</button>
</div>
</template>

<script type="text/ecmascript-6">
export default {
    name: "nextTick",
    data() {
        return {
            msg: "Hello Vue."
        };
    },
    methods: {
        changeMsg() {
            this.msg = "Hello World.";
            setTimeout(() => { // 属于宏任务
                console.log(this.$refs.msgDiv.innerHTML); // Hello World.
            }, 0);
            
            this.$nextTick(() => { // 属于微任务
                console.log(this.$refs.msgDiv.innerHTML); // Hello World.
            });
            
            console.log(this.$refs.msgDiv.innerHTML); // Hello Vue.(没有改变)
        }
    }
};
</script>

点击按钮之后,发现控制台中this.$nextTick()和setTimeout()都发生了改变

可以发现this.$nextTick和setTimeout的效果是一样的,都是将回调方法放入异步队列中

this.$nextTick是当dom发生变化更新后执行的回调。setTimeout只是一个异步延迟执行

什么时候需要用的Vue.nextTick()?

  1. Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载已完成。
  <template>
		<div class="nextTick">
			<div ref="msgDiv">{{msg}}</div>
		</div>
	</template>
	
	<script type="text/ecmascript-6">
	export default {
		name: "nextTick",
		data() {
			return {
				msg: "Hello Vue."
			};
		},
		created() {
			// this.$refs.msgDiv.innerHTML = "更改了内容";  // 报错, 此时DOM并没有渲染
			this.$nextTick(function () {
				this.$refs.msgDiv.innerHTML = "更改了内容";  // 成功修改
			})
		}
	};
	</script>
  1. 当项目中你想在改变DOM元素的数据后基于新的dom做点什么,对新DOM一系列的js操作都需要放进Vue.nextTick()的回调函数中;通俗的理解是:更改数据后当你想立即使用js操作新的视图的时候需要使用它,如上面一开始的例子

官网等着你:https://cn.vuejs.org/v2/api/#Vue-nextTick

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1. 数据更新后立即执行某个操作:Vue.js 更新数据是异步的,如果需要立即执行某个操作(例如获取最新的 DOM 节点),可以使用 `Vue.nextTick` 来确保操作在数据更新后执行。 2. 在 `mounted` 钩子中操作 DOM:在组件的 `mounted` 钩子中,DOM 元素已经渲染完毕,但是此时可能还有一些数据异步更新尚未完成。可以使用 `Vue.nextTick` 来确保在 DOM 渲染完成后再执行相关的操作。 3. 在 `v-for` 渲染后操作 DOM:当使用 `v-for` 指令进行列表渲染时,可能需要在列表渲染完成后对每个列表项进行一些操作,例如绑定事件监听器。可以使用 `Vue.nextTick` 来确保在列表渲染完成后再执行相关的操作。 4. 动态修改组件的 props 值:当需要动态修改组件的 props 值时,可以使用 `Vue.nextTick` 来确保在 props 值修改完成后再执行相关的操作。 5. 监听数据变化并执行操作:当需要监听某个数据的变化,并在数据变化后执行一些操作时,可以使用 `Vue.nextTick` 来确保在数据变化后再执行相关的操作。 6. 在 `watch` 中处理数据变化:当需要在 `watch` 中处理数据变化,并且需要在数据更新后立即执行一些操作时,可以使用 `Vue.nextTick` 来确保在数据更新后再执行相关的操作。 7. 异步渲染组件:当需要异步渲染组件时,可以使用 `Vue.nextTick` 来确保在组件渲染完成后再执行相关的操作。 8. 异步更新数据:当需要异步更新数据时,可以使用 `Vue.nextTick` 来确保在数据更新完成后再执行相关的操作。 9. 在自定义指令中操作 DOM:当需要在自定义指令中操作 DOM 时,可以使用 `Vue.nextTick` 来确保在 DOM 更新完成后再执行相关的操作。 10. 在切换路由后执行操作:当需要在切换路由后执行一些操作,例如重置表单或者滚动到页面顶部,可以使用 `Vue.nextTick` 来确保在路由切换完成后再执行相关的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值