Browse Source

补充文档:过渡效果、自定义页签模板、语言配置

zhaihaoyi 6 years ago
parent
commit
8895b60c43

+ 5 - 5
README.md

@@ -42,12 +42,12 @@ Vue Router Tab 是基于 `Vue Router` 的路由页签组件。
 - [x] 响应路由变化来新增或切换页签
 - [x] 页签关闭和刷新,右键菜单操作
 - [x] [全局](docs/api.md#alive-key)和[针对特定路由](docs/api.md#meta.aliveKey)的页签缓存规则配置
-- [x] [初始页签数据](docs/api.md#tabs),进入页面时默认显示的页签
-- [x] 内置页签和页面[过渡效果](docs/api.md#tab-transition),支持自定义配置
-- [x] 自定义[页签项模板](docs/api.md#自定义页签项模板)
+- [x] [初始页签数据](docs/guide.md#初始展示页签),进入页面时默认显示的页签
+- [x] 内置页签和页面[过渡效果](docs/guide.md#过渡效果),支持自定义配置
+- [x] [自定义页签模板](docs/guide.md#自定义页签模板)
 - [x] [动态更新页签](docs/guide.md#动态更新页签) (标题/图标/提示)
-- [x] [页签离开 (页签关闭/刷新/替换) 前确认](docs/guide.md#页签离开前确认)
-- [x] [语言配置](docs/api.md#i18n):zh-CN (默认) / en,自定义语言
+- [x] [页签页面离开 (页签关闭/刷新/替换) 前确认](docs/guide.md#页面离开确认)
+- [x] [语言配置](docs/guide.md#语言配置):zh-CN (默认) / en,自定义语言
 
 ## 文档:
 [https://bhuh12.github.io/vue-router-tab/](https://bhuh12.github.io/vue-router-tab/)

+ 2 - 1
docs/.vuepress/components/DocLinks.vue

@@ -18,10 +18,11 @@ export default {
 <style lang="stylus" scoped>
 .doc-links
   float right
-  margin-top -5px
+  margin-top -3px
   padding 5px 1em
   background-color #f7f7f7
   border-radius 2em
+  box-shadow inset 0 0 2px rgba(0,0,0,.05)
 
   > a
     margin-right 1em

+ 20 - 72
docs/api.md

@@ -26,10 +26,10 @@
 
   ``` html
   <!-- 取 $route.fullPath -->
-  <router-tab alive-key="fullPath"></router-tab>
+  <router-tab alive-key="fullPath"/>
 
   <!-- 函数方式 -->
-  <router-tab :alive-key="route => route.fullPath + '1'"></router-tab>
+  <router-tab :alive-key="route => route.fullPath + '1'"/>
   ```
 
 ### i18n
@@ -44,44 +44,6 @@
 
 - 默认值: `'zh-CN'`
 
-- 示例:
-
-  - **指定内置语言**
-
-    ``` html
-    <router-tab i18n="en"></router-tab>
-    ```
-
-  - **自定义语言**
-
-    ``` html
-    <router-tab :i18n="lang"></router-tab>
-    ```
-
-    ``` javascript
-    export default {
-      data () {
-        return {
-          lang: {
-            tab: {
-              untitled: 'Untitled Page'
-            },
-            contextmenu: {
-              refresh: 'Refresh This',
-              refreshAll: 'Refresh All',
-              close: 'Close This',
-              closeLefts: 'Close to the Left',
-              closeRights: 'Close to the Right',
-              closeOthers: 'Close Others'
-            },
-            msg: {
-              keepOneTab: 'Keep at least 1 tab'
-            }
-          }
-        }
-      }
-    }
-    ```
 
 ### tabs
 
@@ -123,17 +85,7 @@
 
   - 类型为 `Object` 时,配置参考: [Vue - transition](https://cn.vuejs.org/v2/api/#transition)
 
-- 默认值: `'router-tab-zoom-lb'`
-
-- 示例:
-
-  ``` html
-  <!-- 直接配置过渡名称 -->
-  <router-tab tab-transition="my-transition"></router-tab>
-
-  <!-- 过渡详细配置 -->
-  <router-tab :tab-transition="{ name: 'my-transition', 'enter-class': 'my-transition-enter' }"></router-tab>
-  ```
+- 默认值: `'router-tab-zoom'`
 
 
 ### page-transition
@@ -150,22 +102,6 @@
 }`
 
 
-## RouterTab 插槽
-
-### 页签项
-
-- **示例:**
-  ``` html
-  <router-tab>
-    <template v-slot="{ tab: { id, title, icon, closable }, tabs, index}">
-      <i v-if="icon" class="tab-icon" :class="icon"></i>
-      <span class="tab-index">{{index}}</span>
-      <span class="tab-title">{{title || '未命名页签'}}</span>
-      <i class="tab-close el-icon-close" v-if="closable !== false &&tabs.length > 1" @click.prevent="close(id)"></i>
-    </template>
-  </router-tab>
-  ```
-
 ## RouterTab 实例属性
 
 ### routerTab.activedTab
@@ -176,7 +112,7 @@
 ## RouterTab 实例方法
 
 ::: tip
-在 Vue 实例内部,可以通过 `this.$routerTab` 来访问路由页签实例。例如:调用 `this.$routerTab.close()` 来关闭当前页签。
+在 Vue 实例内部,可以通过 `this.$routerTab` 来访问路由页签实例。例如:调用 `this.$routerTab.close()` 来关闭当前页签。
 :::
 
 ### routerTab.close
@@ -248,20 +184,32 @@
 
 ## RouterPage 路由页面
 
-通过 `<router-tab>` 加载的页面组件实例
+通过 `RouterTab` 加载的页面组件
+
+
+### beforePageLeave
+ 
+  - **参数**: 
+    - `{Function} resolve` 执行后允许离开页签
+    - `{Function} reject` 执行后阻止离开页签
+    - `{Object} tab` 页签信息
+    - `{string} type` 离开类型:`close`: '关闭', `refresh`: '刷新', `replace`: '替换'
+
+  - **说明**: 页面离开确认。页面组件选项,与 `data`, `methods` 并列
+
 
 ### vm.$routerTab
 
-为了方便调用,`<router-tab>` 将实例挂载在 `Vue.prototype` 上。因此,在所有 Vue 组件内部,你都可以通过 `this.$routerTab` 来访问路由页签实例
+为了方便调用,`RouterTab` 将实例挂载在 `Vue.prototype` 上。因此,在所有 Vue 组件内部,您都可以通过 `this.$routerTab` 来访问路由页签实例
 
 
 ### vm.routeTab
 
-**路由页签配置**。`<router-tab>` 通过监听页面组件的 `this.routeTab` 来更新页面对应页签的标题、图标、提示
+**路由页签配置**。`RouterTab` 通过监听页面组件的 `this.routeTab` 来更新页面对应页签的标题、图标、提示
 
 ### vm._isRouterPage
 
-**是否是路由页面**:在通过 `<router-tab>` 加载的页面组件内部,访问 `this._isRouterPage` 会返回 `true`
+**是否是路由页面**:在通过 `RouterTab` 加载的页面组件内部,访问 `this._isRouterPage` 会返回 `true`
 
 ::: tip
 应用:在需要给路由页面添加全局混入 `mixin` 时,可在生命周期钩子( `created` 之后)里判断 `this._isRouterPage`

+ 226 - 45
docs/guide.md

@@ -50,7 +50,7 @@ new Vue({
 配置参考: [RouterTab Props](api.md#routertab-props)
 
 ::: danger
-`vue-router-tab` 仅支持单例模式,请勿在同一个页面中引入多个 `<router-tab>` 组件!
+`RouterTab` 仅支持单例模式,请勿在同一个页面中引入多个 `RouterTab` 组件!
 :::
 
 **示例:**
@@ -125,11 +125,11 @@ export default new Router({
 
 ### 打开/切换页签
 
-`vue-router-tab` 通过响应路由变化来新增或切换页签,直接使用 `vue-router` 提供的方法即可。
+`RouterTab` 通过响应路由变化来新增或切换页签,直接使用 `vue-router` 提供的方法即可。
 
 参考文档:[Vue Router 导航](https://router.vuejs.org/zh/guide/essentials/navigation.html)
 
-<doc-links demo="/default/page/1"></doc-links>
+<doc-links demo="/default/"></doc-links>
 
 1. **`router-link` 组件方式**
 
@@ -147,7 +147,7 @@ export default new Router({
 
 2. **通过 `router.push`、`router.replace`、`router.go`**
 
-  注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push。
+  注意:在 Vue 实例内部,您可以通过 $router 访问路由实例。因此您可以调用 this.$router.push。
 
   ``` javascript
   // 如果需要全新打开请加上:
@@ -157,13 +157,13 @@ export default new Router({
 
 ### 关闭页签
 
-您可以通过 `router-tab` 的实例方法 [`routerTab.close(location, fullMatch?)`](api.md#routertab-close) 来关闭页签
+您可以通过 `RouterTab` 的实例方法 [`routerTab.close(location, fullMatch?)`](api.md#routertab-close) 来关闭页签
 
 ::: tip
-在 Vue 实例内部,你可以通过 `$routerTab` 访问路由页签实例。因此你可以调用 `this.$routerTab.close`。
+在 Vue 实例内部,您可以通过 `$routerTab` 访问路由页签实例。因此您可以调用 `this.$routerTab.close`。
 :::
 
-<doc-links api="#routertab-close" demo="/default/page/1"></doc-links>
+<doc-links api="#routertab-close" demo="/default/"></doc-links>
 
 **关闭当前页签**
 
@@ -195,9 +195,9 @@ this.$routerTab.close('/page/1', false)
 
 ### 刷新页签
 
-您可以通过 `router-tab` 的实例方法 [`routerTab.refresh(location, fullMatch?)`](api.md#routertab-refresh) 来刷新页签
+您可以通过 `RouterTab` 的实例方法 [`routerTab.refresh(location, fullMatch?)`](api.md#routertab-refresh) 来刷新页签
 
-<doc-links api="#routertab-refresh" demo="/default/page/1"></doc-links>
+<doc-links api="#routertab-refresh" demo="/default/"></doc-links>
 
 **刷新当前页签**
 
@@ -228,18 +228,18 @@ this.$routerTab.close('/page/1', false)
 
 ### 刷新所有页签
 
-您可以通过 `router-tab` 的实例方法 [`routerTab.refreshAll(force?)`](api.md#routertab-refreshall) 来刷新所有页签
+您可以通过 `RouterTab` 的实例方法 [`routerTab.refreshAll(force?)`](api.md#routertab-refreshall) 来刷新所有页签
 
 **刷新所有页签**
 
 ``` js
-vm.$routerTab.refreshAll()
+this.$routerTab.refreshAll()
 ```
 
 **强制刷新所有页签**,忽略页面组件的 `beforePageLeave` 配置
 
 ``` js
-vm.$routerTab.refreshAll(true)
+this.$routerTab.refreshAll(true)
 ```
 
 
@@ -247,30 +247,147 @@ vm.$routerTab.refreshAll(true)
 
 前面的内容已经能满足大部分使用场景了,您还可以根据下面的内容实现更多功能。
 
+### 过渡效果
+
+您可以通过配置组件的 `tab-transition` 和 `page-transition` 属性,分别替换默认的页签和页面过渡效果
+
+::: warning
+- 如果是组件作用域内的 CSS(配置了 `scoped`),需要在选择器前添加 `/deep/`才能生效
+
+- 页签项 `.router-tab-item` 默认设置了 `transition` 和 `transform-origin` 的样式,您可能需要覆盖它已避免影响到自定义的过渡效果
+:::
+
+<doc-links api="#tab-transition" demo="/transition/"></doc-links>
+
+**页签过渡效果-示例:**
+
+``` html {2,6}
+<template>
+  <router-tab tab-transition="tab-scale"/>
+</template>
+
+<style lang="scss" scoped>
+/deep/ .tab-scale {
+  &-enter-active,
+  &-leave-active {
+    transition: opacity .5s, transform .5s;
+  }
+
+  &-enter,
+  &-leave-to {
+    opacity: 0;
+    transform: scale(1.5);
+  }
+}
+</style>
+```
+
+<doc-links api="#page-transition" demo="/transition/"></doc-links>
+
+**页面过渡效果-示例:**
+
+``` html {2,6}
+<template>
+  <router-tab page-transition="page-fade"/>
+</template>
+
+<style lang="scss" scoped>
+/deep/ .page-fade {
+  &-enter-active,
+  &-leave-active {
+    transition: opacity .5s;
+  }
+
+  &-enter,
+  &-leave-to {
+    opacity: 0;
+  }
+}
+</style>
+```
+
+#### 详细配置
+
+您还可以使用对象的方式设置 `tab-transition` 和 `page-transition` 的值,以实现详细的过渡效果配置
+
+配置参考: [Vue - transition](https://cn.vuejs.org/v2/api/#transition)
+
+``` html
+<router-tab :tab-transition="{
+  name: 'my-transition',
+  'enter-class': 'my-transition-enter'
+}"/>
+```
+
+
+### 自定义页签模板
+
+通过组件的默认作用域插槽,我们可以自定义页签显示的内容
+
+插槽的作用域提供以下属性供模板使用:
+  - **tab** {Object} 页签项信息,包括 `id`, `title`, `icon`, `closable` 等
+  - **tabs** {Array} 页签列表
+  - **index** {Number} 索引
+
+<doc-links demo="/slot/"></doc-links>
+
+**示例:**
+
+``` html {2}
+<router-tab>
+  <template v-slot="{ tab: { id, title, icon, closable }, tabs, index}">
+    <i v-if="icon" class="tab-icon" :class="icon"></i>
+    <span class="tab-title">{{title || '未命名页签'}}</span>
+    <span class="tab-badge">{{index}}</span>
+    <i class="tab-close el-icon-close" v-if="closable !== false &&tabs.length > 1" @click.prevent="$routerTab.close(id)"></i>
+  </template>
+</router-tab>
+```
+
+
 ### 初始展示页签
 
-进入页面时默认显示的页签
+通过配置组件的 `tabs` 属性,可以设置进入页面时默认显示的页签
 
-<doc-links api="#tabs" demo="/initial-tabs/page/1"></doc-links>
+<doc-links api="#tabs" demo="/initial-tabs/"></doc-links>
 
-**示例**:
+**示例**
 
   ``` html
-  <!-- 默认页签 -->
-  <router-tab :tabs="[
-    '/page1',
-    { to: '/page/2', title: '页面2' },
-    { to: '/page/3', closable: false },
-    { to: {
-      name: 'page',
-      params: { id: 4 },
-      query: { t: 2 }
-    }},
-    { to: '/page/2?t=1', title: '页面2-1' }
-  ]"></router-tab>
-  <!-- '/page/2'与'/page/2?t=1'两个路由的aliveKey一致,将只保留前一个页签 -->
+  <router-tab :tabs="tabs"/>
   ```
 
+  ``` javascript {7}
+  export default {
+    data () {
+      return {
+        // 默认页签项
+        tabs: [
+          // 推荐 fullPath 方式配置默认页签项。RouterTab 会自动获取路由里的页签配置
+          '/page/1',
+
+          // 设置初始 title,用于需要动态展示页签信息的路由页面
+          { to: '/page/2', title: '页面2', icon: 'icon-page' },
+
+          // 设置 closable 为 false,可以禁止页签被关闭
+          { to: '/page/3', closable: false },
+
+          // 也可以 location 方式设置默认页签项
+          {
+            to: {
+              name: 'page',
+              params: { id: 4 },
+              query: { t: 2 }
+            }
+          },
+          
+          // 此页面与'/page/2'的aliveKey一致,将只保留先设置的页签
+          { to: '/page/2?t=1', title: '页面2-1' }
+        ]
+      }
+    }
+  }
+  ```
 
 ### 动态更新页签
 
@@ -280,9 +397,7 @@ vm.$routerTab.refreshAll(true)
 
 **示例:**
 
-``` javascript
-// src/views/Page.js
-
+``` javascript {8,11}
 export default {
   name: 'page',
   mounted () {
@@ -303,9 +418,57 @@ export default {
 }
 ```
 
-### 页签离开前确认
 
-当页签**关闭**、**刷新**或**替换**时会触发 `beforePageLeave`,使用 `Promise` 的 `resolve` 和 `reject` 来允许和阻止页签页面的离开。
+### 语言配置
+
+通过配置组件的 `i18n` 属性,可以设置组件显示的语言 (主要表现为页签右键菜单)。
+
+
+`RouterTab` 默认语言是 `zh-CN`,另外内置了 `en`。
+
+<doc-links api="#i18n" demo="/language/"></doc-links>
+
+**指定组件显示为英文**
+
+``` html
+<router-tab i18n="en"/>
+```
+
+**自定义的语言**
+
+``` html
+<router-tab :i18n="lang"/>
+```
+
+``` javascript
+export default {
+  data () {
+    return {
+      lang: {
+        tab: {
+          untitled: 'Untitled Page'
+        },
+        contextmenu: {
+          refresh: 'Refresh This',
+          refreshAll: 'Refresh All',
+          close: 'Close This',
+          closeLefts: 'Close to the Left',
+          closeRights: 'Close to the Right',
+          closeOthers: 'Close Others'
+        },
+        msg: {
+          keepOneTab: 'Keep at least 1 tab'
+        }
+      }
+    }
+  }
+}
+```
+
+
+### 页面离开确认
+
+当页签**关闭**、**刷新**或**替换**时会触发 `beforePageLeave`,通过 `Promise` 的 `resolve` 和 `reject` 来允许或者阻止页签页面的离开。
 
 ::: warning
 
@@ -315,27 +478,45 @@ export default {
 [`onbeforeunload`](https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload)
 :::
 
-<doc-links demo="/default/page-leave"></doc-links>
+<doc-links demo="/initial-tabs/page-leave"></doc-links>
 
 **示例:**
 
-``` javascript
-// src/views/Page.js
-
+``` javascript {3,17,23,25,30}
 export default {
-  name: 'page',
-
-  // 路由页面离开前确认
+  // 页面离开前确认
   beforePageLeave (resolve, reject, tab, type) {
-    let action = (type === 'close' && '关闭') ||
-      (type === 'refresh' && '刷新') ||
-      (type === 'replace' && '替换')
-
+    // 离开类型
+    const types = {
+      close: '关闭',
+      refresh: '刷新',
+      replace: '替换'
+    }
+
+    const action = types[type]
+
+    const msg = `您确认要${action}页签“${tab.title}”吗?`
+
+    // 值未改变,则直接离开页签
+    if (this.editValue === this.value) {
+      resolve()
+      return
+    }
+
+    // 值改变则确认提示
+    if (confirm(msg)) {
+      resolve()
+    } else {
+      reject('拒绝了页面离开')
+    }
+
+    /*
     // 此处使用了 Element 的 confirm 组件
     // 需将 closeOnHashChange 配置为 false,以避免路由切换导致确认框关闭
-    this.$confirm(`您确认要${action}页签“${tab.title}”吗?`, '提示', { closeOnHashChange: false })
+    this.$confirm(msg, '提示', { closeOnHashChange: false })
       .then(resolve)
       .catch(reject)
+    */
   }
 }
 ```

+ 2 - 1
src/App.vue

@@ -33,6 +33,7 @@ export default {
         title: 'RouterTab 配置',
         data: [
           { text: '默认配置', to: '/default/' },
+          { text: '过渡效果', to: '/transition/' },
           { text: '初始展示页签', to: '/initial-tabs/' },
           {
             text: '语言配置',
@@ -49,7 +50,7 @@ export default {
         title: '页面配置',
         data: [
           { text: '动态更新页签配置', to: '/default/tab-dynamic' },
-          { text: '页面离开提示', to: '/default/page-leave' }
+          { text: '页面离开确认', to: '/initial-tabs/page-leave' }
         ]
       }]
     }

+ 38 - 4
src/assets/scss/demo.scss

@@ -25,7 +25,7 @@ a:link {
   transition: color .3s ease-in-out;
 }
 
-
+/* 布局 */
 .app-ct {
   display: flex;
   flex-direction: column;
@@ -33,7 +33,6 @@ a:link {
   height: 100%;
 
   .app-hd {
-    flex: none;
     display: flex;
     position: relative;
     z-index: 99;
@@ -83,7 +82,8 @@ a:link {
   }
 
   .app-bd {
-    flex: auto;
+    flex: 1;
+    height: 0;
     position: relative;
   }
 }
@@ -197,4 +197,38 @@ $just-trans: all .2s ease-in-out;
   padding: 15px;
   font-size: 14px;
   line-height: 1.5;
-}
+}
+
+/* UI */
+
+// 强提示
+.text-strong {
+  font-weight: 600;
+  font-size: 1.2em;
+  color: #f50;
+}
+
+// 按钮
+.demo-btn {
+  display: inline-block;
+  margin: 0 1em .5em 0;
+  padding: 3px 8px;
+  font-size: 14px;
+  color: #333;
+  text-decoration: none;
+  cursor: pointer;
+  border-radius: 3px;
+  border: 1px solid #ccc;
+  transition: all .3s ease;
+
+  &:hover {
+    color: $color;
+    border-color: $color;
+  }
+
+  &:active {
+    $activeColor: mix(#000, $color, 20%);
+    color: $activeColor;
+    border-color: $activeColor;
+  }
+}

+ 5 - 5
src/components/layout/Slot.vue

@@ -2,11 +2,11 @@
   <main class="app-main">
     <router-tab>
       <template v-slot="{ tab: { id, title, icon, closable }, tabs, index}">
-      <i v-if="icon" class="tab-icon" :class="icon"></i>
-      <span class="tab-title">{{title || '未命名页签'}}</span>
-      <span class="tab-badge">{{index}}</span>
-      <i class="tab-close el-icon-close" v-if="closable !== false &&tabs.length > 1" @click.prevent="$routerTab.close(id)"></i>
-    </template>
+        <i v-if="icon" class="tab-icon" :class="icon"></i>
+        <span class="tab-title">{{title || '未命名页签'}}</span>
+        <span class="tab-badge">{{index}}</span>
+        <i class="tab-close el-icon-close" v-if="closable !== false &&tabs.length > 1" @click.prevent="$routerTab.close(id)"></i>
+      </template>
     </router-tab>
   </main>
 </template>

+ 32 - 0
src/components/layout/Transition.vue

@@ -0,0 +1,32 @@
+<template>
+  <main class="app-main">
+    <router-tab page-transition="page-fade" tab-transition="tab-scale"/>
+  </main>
+</template>
+
+<style lang="scss" scoped>
+/deep/ .page-fade {
+  &-enter-active,
+  &-leave-active {
+    transition: opacity .5s;
+  }
+
+  &-enter,
+  &-leave-to {
+    opacity: 0;
+  }
+}
+
+/deep/ .tab-scale {
+  &-enter-active,
+  &-leave-active {
+    transition: opacity .5s, transform .5s;
+  }
+
+  &-enter,
+  &-leave-to {
+    opacity: 0;
+    transform: scale(1.5);
+  }
+}
+</style>

+ 6 - 1
src/router.js

@@ -26,7 +26,7 @@ let pageRoutes = [{
   path: 'page-leave',
   component: importPage('PageLeave'),
   meta: {
-    title: '页面离开提示',
+    title: '页面离开确认',
     icon: 'rt-icon-contact'
   }
 }]
@@ -40,6 +40,11 @@ export default new Router({
     component: importLayout('Default'),
     redirect: '/default/page/1',
     children: pageRoutes
+  }, {
+    path: '/transition/',
+    component: importLayout('Transition'),
+    redirect: '/transition/page/1',
+    children: pageRoutes
   }, {
     path: '/initial-tabs/',
     component: importLayout('InitialTabs'),

+ 16 - 47
src/views/Page.vue

@@ -2,37 +2,37 @@
   <div class="app-page">
     <h2 @click="click">页面{{pageId}}</h2>
 
-    <p class="page-time-tips">你在 <strong class="time">{{pageTime}}</strong> 秒前打开本页面</p>
+    <p>你在 <strong class="text-strong">{{pageTime}}</strong> 秒前打开本页面</p>
 
     <h3>页签操作</h3>
 
-    <div class="btn-group">
-      <router-link class="btn" :to="'../page/'+ nextId">打开“页面{{nextId}}”</router-link>
-    </div>
+    <p>
+      <router-link class="demo-btn" :to="'../page/'+ nextId">打开“页面{{nextId}}”</router-link>
+    </p>
 
-    <div class="btn-group" v-if="prevId > 0">
-      <router-link class="btn" :to="'../page/'+ prevId">打开“页面{{prevId}}”</router-link>
+    <p v-if="prevId > 0">
+      <router-link class="demo-btn" :to="'../page/'+ prevId">打开“页面{{prevId}}”</router-link>
 
       <router-link
-        class="btn"
+        class="demo-btn"
         :to="'../page/'+ prevId"
         @click.native="$routerTab.refresh('../page/'+ prevId)"
       >
         全新打开“页面{{prevId}}”
       </router-link>
-    </div>
+    </p>
 
-    <div class="btn-group">
-      <a class="btn" @click="$router.push('../tab-dynamic')">打开“动态更新页签”</a>
+    <p>
+      <a class="demo-btn" @click="$router.push('../tab-dynamic')">打开“动态更新页签”</a>
 
-      <a class="btn" @click="$routerTab.close('../tab-dynamic')">关闭“动态更新页签”</a>
-    </div>
+      <a class="demo-btn" @click="$routerTab.close('../tab-dynamic')">关闭“动态更新页签”</a>
+    </p>
 
-    <div class="btn-group">
-      <a class="btn" @click="$routerTab.refresh()">刷新当前页面</a>
+    <p>
+      <a class="demo-btn" @click="$routerTab.refresh()">刷新当前页面</a>
 
-      <a class="btn" @click="$routerTab.close()">关闭当前页面</a>
-    </div>
+      <a class="demo-btn" @click="$routerTab.close()">关闭当前页面</a>
+    </p>
 
     <div>
       <input type="text" />
@@ -71,37 +71,6 @@
 
 <style lang="scss" scoped>
 .app-page {
-  .btn {
-    display: inline-block;
-    margin-bottom: 1em;
-    margin-right: 1em;
-    padding: 2px 8px;
-    font-size: 14px;
-    color: #333;
-    text-decoration: none;
-    cursor: pointer;
-    border-radius: 3px;
-    border: 1px solid #ccc;
-    transition: all .3s ease;
-
-    &:hover {
-      color: $color;
-      border-color: $color;
-    }
-
-    &:active {
-      $activeColor: mix(#000, $color, 20%);
-      color: $activeColor;
-      border-color: $activeColor;
-    }
-  }
-
-  .page-time-tips {
-    .time {
-      font-size: 1.2em;
-      color: red;
-    }
-  }
 
   .route-info {
     min-width: 300px;

+ 32 - 8
src/views/PageLeave.vue

@@ -1,16 +1,31 @@
 <template>
   <div class="app-page">
-    <h2>页面离开提示</h2>
+    <h2>页面离开确认</h2>
+
+    <p>你在 <strong class="text-strong">{{pageTime}}</strong> 秒前打开本页面</p>
+
     <p>
-      修改输入框的值后,页面在页签关闭/刷新/被替换时将会确认提示
+      <strong class="text-strong">修改输入框的值</strong>后,页面在页签关闭/刷新/被替换时将会确认提示
     </p>
+
     <input type="text" v-model="editValue">
+
+    <p>
+      <a class="demo-btn" @click="$routerTab.refresh()">刷新</a>
+
+      <a class="demo-btn" @click="$routerTab.close()">关闭</a>
+
+      <router-link class="demo-btn" :to="`?id=${+(this.$route.query.id || 0) + 1}`">替换</router-link>
+    </p>
   </div>
 </template>
 
 <script>
+import pageTimer from '@/mixins/pageTimer'
+
 export default {
   name: 'PageLeave',
+  mixins: [pageTimer],
 
   data () {
     let value = '初始值'
@@ -20,18 +35,27 @@ export default {
     }
   },
 
-  // 页面离开前提示
+  // 页面离开前确认
   beforePageLeave (resolve, reject, tab, type) {
-    const action = (type === 'close' && '关闭') ||
-      (type === 'refresh' && '刷新') ||
-      (type === 'replace' && '替换')
+    // 离开类型
+    const types = {
+      close: '关闭',
+      refresh: '刷新',
+      replace: '替换'
+    }
+
+    const action = types[type]
 
     const msg = `您确认要${action}页签“${tab.title}”吗?`
 
-    // 值未改变,直接离开;值改变则确认提示
+    // 值未改变,则直接离开页签
     if (this.editValue === this.value) {
       resolve()
-    } else if (confirm(msg)) {
+      return
+    }
+
+    // 值改变则确认提示
+    if (confirm(msg)) {
       resolve()
     } else {
       reject('拒绝了页面离开')