Vue 单页应用开发

hash模式 & history模式

单页应用最强大的地方在于:虽然我们通过点击router-link等方式令文档更新了,但是页面并没有被重新加载。
我们可以用这段代码观察页面有没有重新加载:

mounted() {
    (function task(i = 0) {
        console.log(i);
        setTimeout(() => task(++i), 200);
    })();
},

我们知道单页有两种路由模式,在实例化Router对象时指定路由模式:

new Router({
    mode: 'history',
    routes: [
        {path: '/', component: App},
    ],
});

history模式下,如何保证页面不被重新加载呢?请先了解router-link在history模式下的工作原理。
在 HTML5 history 模式下,router-link 会守卫点击事件,让浏览器不再重新加载页面。

history.pushState(state, title, url)函数

history.pushState用于在浏览历史中添加历史记录,但是并不触发跳转,此方法接受三个参数,依次为:

state    一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null。
title    新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null。
url    新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。

当我们点击router-link时,实际上是调用了router.push()函数,这个函数就是history.pushState()实现的。
因此,我们如果需要保留a标签的href实现单页内跳转,可以拦截浏览器默认行为,即在@click.prevent事件中调用router.push()即可。

<a href="/topath" @click=go>Click Me</a>

methods: {
    go(event) {
        event.preventDefault();
        // const dist = (event.target.href.split(/https?://[^/]+/)[1]);
        // console.log(dist);
        const dist = event.target.getAttribute('href');
        if (dist.match(/^https?:///)) {
            return document.location.href = dist;
        }
        this.$router.push(dist);
    },
},

更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

<a href="/topath" @click.prevent=go>Click Me</a>

methods: {
    go(event) {
        // event.preventDefault(); 不需要在代码中取消浏览器默认行为
...
        this.$router.push(dist);
    },
},

webpack-dev-server配合history模式

webpack.config.js

    devServer: {
        contentBase: home + '/dist',
        //
        historyApiFallback: {
            index: '/index.html',
        },
    },
/**
ℹ 「wds」: Content not from webpack is served from /home/kasumi/vue/SingePageApp/new/apps/mybrowser/dist
ℹ 「wds」: 404s will fallback to /index.html
*/

rewrites实现路由:

    historyApiFallback: {
      index: 'build/index.html',
      rewrites: [
          { from: /^/admin/, to: 'build/admin.html' },
      ],
    },

<router-link><a> 的恩怨情仇

router-link默认渲染一个<a>标签,可以通过tag参数改变,使得span等也具有点击后在页内跳转的能力。
对于子组件写死的<a>标签,只能在事件中使用js来push跳转了。

END

原文地址:https://www.cnblogs.com/develon/p/12582110.html