目前我们实现了即时搜寻显示书名相符的书单资料,但是当我切换到其他路由之後又想再回到上一页的搜寻结果,或是直接在当前路径重新整理页面时,搜寻栏位就被清空了,而书单资料因为搜寻栏位无字串值可供辨别,因此连带失去筛选条件,一切回到最一开始的样子。
事实上,网站中的栏位并不会记住使用者的输入值,甚至是存进 Vuex 的资料也会在刷新页面之後被清空,因此才需要每次在不同时机进入路由或元件时,都需要发送 API 重新取得资料再渲染到画面上,又或者是透过暂存在用户端的 LocalStorage 或 Cookie 以便日後取用。
以为没有地方可以存取关键字,但其实近在眼前就有个可以利用的工具,就是路由!大家可以观察最常使用的 Google 搜寻,假设我们在搜寻栏位输入「vue.js」,搜寻结果会导向「 https://www.google.com/search?q=vue.js 」(& 後面暂且略过),接着改搜寻「vuex」,变成导向「 https://www.google.com/search?q=vuex 」,有发现什麽相同和差别之处了吗?
$route.query
物件相同的是两者都在 /search 路由之後出现「?q=」,差别在於後方所接的是各自输入的搜寻关键字,而我们就是要利用「?」来记录搜寻字词,问号後方所接的正是「query」查询字串,其组成通常是一对 key 和 value,假设一段网址最後为「?search=java&user=john」(多组 query 中间以 & 串连) ,则透过 $route.query
便能取得 query 物件的内容为 {search: 'java', user: 'john'}
。
知道方法之後,实际应用在我们的专案范例上:
原本在 <BookList> 元件上监听的 input 事件是将输入值直接赋值给 inputText
prop,再传递给子元件渲染在 input 上;由於要在监听事件增加其他执行内容,因此可改为监听 methods 中的函式 searchBookName
。
<div class="All">
<BookList
navTitle="All"
:bookList="books"
:inputText="searchText"
@searchBook="searchBookName($event)"
/>
<!-- 原先写法:@searchBook="searchText = $event.target.value" -->
</div>
在searchBookName
函式除了原本的赋值工作,另外追加设置 $router.replace
,让每次即时输入字串的同时,都会将输入值列入 query 物件中,并且更新 key 为 search
的 value 内容,於是每当输入字串的同时,都会重新导向连动输入字串的 query 路径。
methods: {
searchBookName(event) {
this.searchText = event.target.value;
this.$router.replace({
name: this.$route.name,
query: { search: event.target.value },
});
},
},
接着在元件内使用的导航守卫 beforeRouteEnter
进行判断,当路径带有指定 key 为 search
的 query 物件时,要先将 search
对应的 value 赋值给 searchText
,透过 inputText
prop 传给子元件,因此当重新整理页面时,赶在画面渲染好之前,已经将重整页面之前的搜寻值再次渲染至 input 栏位中了。
这边需要留意的是,beforeRouteEnter
阶段无法取得 this
,因为其会在导航确认之前被调用,当时准备进入的元件实例的尚未完成创建,不过可以在 next
callback 中透过 vm
取得实例,再利用 to
取得目标路由物件中的 query 物件。
beforeRouteEnter(to, from, next) {
next((vm) => {
if (to.query.search) {
vm.searchText = to.query.search;
}
});
},
data() {
return {
searchText: "",
};
},
设置完成後,测试看看在搜寻栏输入「vue」,检查一下以下三种情境,无误的话就代表成功了!
$router.replace
VS $router.push
简单说明两者的差别在於 $router.replace
不会向 history 留下纪录。以上述范例为例,若使用 $router.push
,则当我输入「java」之後,按下返回上一页,会使路径变成「 http://localhost:8080/book/all?search=jav 」;而使用 $router.replace
的话,上一页会是进入当前路由的上一个页面。
相关实作也可以应用在登入流程,假设一个使用者的动线是从首页进入会员登入页,若登入成功之後应该透过 $router.replace
将他导向会员後台,此时他若想要返回上一页,就会因为在登入页没有留下 history 纪录,而跳过登入页又再次回到一开始的进入点首页,因为对一个登入成功的使用者来说,不适合以登入状态能够再次回到登入页。
【DAY 17】微软生产力平台 Microsoft Power Platform 补充 — Code...
欧阳克是谁杀的? 这个this是谁?要看凶手是谁而定! 前面有提到,这个e是在当事件发生时,事件处...
职涯在走,铁人赛文章一定要有。 小画家小问题跟改善方法 tags: 铁人赛 嗨,大家安安,今天来说...
阿嬷都看得懂的响应式网页设计在干嘛 还记得前两天我们在玩贴纸簿的时候,问过这个问题:我们的整个网页到...
话不多说先上图 从左到右依序执行,最後该函式会再呼叫自己一次,图中淡化的区块是下个章节的主题 然後把...