Vue 全站緩存之 vue-router-then :先後頁數據傳遞

連續預告了好幾天,總算寫到這篇了。javascript

系列篇1:Vue 全站緩存之 keep-alive : 動態移除緩存html

系列篇2:Vue 全站緩存二:如何設計全站緩存vue

本篇爲系列篇3:Vue 全站緩存之 vue-router-then :先後頁數據傳遞java

系列篇4:Vue 全站緩存之 vue-router-then :實現原理git

前言

在前文 Vue 全站緩存之 keep-alive : 動態移除緩存Vue 全站緩存二:如何設計全站緩存 中,咱們實現了全站緩存的基礎框架,在頁面之間後退或同層頁面之間跳轉時能夠複用緩存,減小了請求頻率,提高了用戶體驗,最讚的是,開發邏輯理論上會簡單直觀不少。github

出現了一個新需求

在父子組件之間,數據能夠經過 Prop 和 $emit 事件來互相傳遞數據。vue-router

在本系列裏,咱們研究的主題是先後頁的組件緩存與複用,由於使用了 keep-alive 的緩存特性,雖然前一頁在界面上已經被移出,在系統裏,先後頁組件對象仍然是同時存在的。vuex

因而,一個新的需求天然而然的出現了,就是如何在先後頁組件之間傳遞數據npm

store 模式和 vuex

前文也曾說過,爲了在不一樣頁面之間傳遞或共用數據,目前主流的方案是使用sotre模式或引入 vuex , 做爲先後頁面以外的公共組件,全部頁面均可以直接對其存取數據。連接promise

這是一個很好的解決方案,能夠兼容不少場景,並且很值得繼續挖掘這個特性哦。

留個坑,最近在研究如何將這個Flux特性發揮到極致。

懶是人類進步的源泉

就我我的而言,我是很極端的懶,vuex 的確能解決先後頁數據交流的問題,然而許多時候我僅僅只是打開一個頁面選擇一個客戶回來而已。

若是能寫成

<input v-model="searchText">
複製代碼

我可不想寫成:

<input v-bind:value="searchText" v-on:input="searchText = $event.target.value" >
複製代碼

因此,仍是商城的例子,若是在訂單頁面須要打開一個新頁面去選擇一個地址,我可不想從 vuex 那裏繞一大圈寫一堆State Mutation Action ,我但願寫成下面這樣:

<!-- buySomething.vue -->
<inputSelectedAddress v-model="item.addressID" v-model-link="'/select_address'" placeholder="選擇地址" /> 

<!-- selectAddress.vue -->
<template>
    <ul>
        <li @click="selectOneAddress(1)">北京路南廣場東門101</li>
        <li @click="selectOneAddress(2)">上海城下水道左邊202</li>
    </ul>
</template>
<script> methods:{ selectOneAddress:function(addressID){ this.$emit('input',addressID); this.$router.go(-1); } } </script>
複製代碼

打開一個地址選擇頁,選擇好地址後,直接將地址 id 傳回來,甚至直接和 v-model 兼容起來,而後該幹啥幹啥,這樣的場景想一想就很贊哇。

v-model-link

在上文的示例代碼裏出現了v-model-link這個自定義指令,這個指令來自插件 vue-router-then 的一個特性。連接

v-model-link的基本用法:

  • 在綁定v-model的元素上使用v-model-link指令指向一個新頁面
  • 在新頁面裏用戶互動以後,使用$emit觸發一個input事件將數據傳遞回來便可更新v-model所對應的值。

請注意此處的場景差別:$emit原本是用來進行父子組件的事件傳遞的,在此處被挪用到了先後頁組件之間傳遞事件,

原理簡述:

  • v-model-link的值是一個 url 地址,在點擊該指令所在的 DOM 元素後,會跳轉到該 url 頁面,並在新的頁面裏監聽input事件反饋給指令所在的DOM 元素或組件。
  • 由於v-model就是一個input事件的語法糖,因此其對應的值會受input事件影響。
  • 由於緩存的存在,前一頁組件沒有被銷燬,這纔是vue-router-then這個插件成功使用的基礎。
    • 因此,請注意正確設定各路由頁面的層級關係,若是離開頁面時組件被銷燬了,可就無法玩了。

vue-router-then

vue-router-then的核心本質就是實現了在當前頁操做下一頁組件的功能,v-model-link只是該功能基礎上的一個語法糖指令,固然也是最重要最經常使用的特性指令。

如何安裝

npm install vue-router-then --save;
複製代碼
import Vue from 'vue'
import router from './router'

import routerThen from 'vue-router-then';
routerThen.initRouter(router)
Vue.use(routerThen)
複製代碼

使用方法一:在當前頁面操做下一頁面的組件對象

該插件名爲vue-router-then,顧名思義,其最大的特性是給router的方法(push,replace,go)返回了一個promise對象,並使用新頁面的vm做爲參數在then方法裏供處理。

methods:{
    clickSomeOne:function(){
        this.$routerThen.push('/hello_world').then(vm=>{
            // 此處的 vm 即爲新頁面hello_world的組件對象
            console.log(vm);
        });
    },
}
複製代碼

使用方法二:使用$routerThen.modelLink在當前頁得到下一頁面組件上報的input事件中的值

$routerThen中還新增了一個自定義方法modelLink,用來處理下一頁面上報的值,該方法一樣能夠操控下一頁面組件對象。

methods:{
    jumpToNextPage:function(value){
        this.$routerThen.modelLink('/select_price',value=>{
            // 此處得到select_price頁面$emit出來的 input 事件中的值
            console.log(value);
        }).then(vm=>{
            // 此處的 vm 即爲新頁面select_price的組件對象
            console.log(vm);
        });
    },
}
複製代碼

使用方法三:配合 v-model 使用自定義指令 v-model-link

<inputCustomer v-model="item.customerID" v-model-link="'/select_customer'" />
複製代碼

再舉個栗子

在咱們的記應收這款記帳APP中,有一個選擇客戶的頁面,該頁面支持搜索客戶,若是搜索不到客戶,則應該支持以關鍵字去創建一個客戶並選中新客戶。

也就是說涉及編輯合同->選擇客戶->新建客戶這三個頁面,其中核心代碼以下:

編輯合同:

<!-- InitEditContractDetail.vue -->
<inputCustomer v-model="item.customerID" v-model-link="'/customer/select_customer'"/>
複製代碼

選擇客戶:

<!-- InitSelectCustomer.vue -->
<template>
    <div>
        <input type="text" v-model="keyword" />
        <a @click="newCustomerJumpLink">新增</a>
    </div>
</template>
<script> methods:{ newCustomerJumpLink(){ this.$routerThen.modelLink('/customer/edit',value=>{ this.newCustomerAdded(value) }).then(vm=>{ if (this.keyword) { vm.$set(vm.item,'name',this.keyword); } }); }, newCustomerAdded:function(customerID){ this.$emit('input',customerID); this.$router.go(-1); }, } </script>
複製代碼

新增客戶:

<!-- InitCustomerEdit.vue -->
<template>
    <div>
        <div>客戶名稱</div>
        <input type="text" v-model="item.name" />
        <div class="btn_submit" @click="submit">提交</div>
    </div>
</template>

<script> methods:{ submit:function(){ this.$emit('input',customerID); this.$router.go(-1); } } </script>
複製代碼

後語

到此時,應付大部分的項目場景應該沒問題了。

後續還會發幾篇相關文章,研究 vue-router-then 的原理,研究全站緩存這種極端狀況下用戶的數據又會發生什麼奇怪的變化呢,又或者還能玩出哪些更有意思的花樣呢。

敬請期待。

更新續篇:Vue 全站緩存之 vue-router-then 實現原理

原文來自阿星的博客:wanyaxing.com/blog/201807…

相關文章
相關標籤/搜索