第5章 Vue 路由

第5章 Vue 路由

5.1 初始路由 & vue-router

初识路由

后端路由,每次跳转都会重新访问服务器,会有延迟

前端路由,访问新页面的时候仅仅是变换了一下 hash 值而已,无延迟,提升用户体验

后端路由前端路由
http://localhost/home/index.html#/home
http://localhost/about/index.html#/about

vue-router

官方推出的路由管理器,用来管 URL

有两个模式,hash 模式有 #,不美观,而 history 模式没有

使用 URL 的 hash 来模拟一个完整的 URL,当 URL 改变时,页面不会重新加载
# 就是 hash 符号,中文名为哈希符或锚点,哈希符后的值 叫哈希值
三个基本概念
route表示一条路由
routes表示一组路由
router是一个机制,充当路由管理者的角色,找到组里对应的路由

vue-router 的基本使用

v u e − r o u t e r   的 基 本 使 用 vue-router\ 的基本使用 vuerouter 使

<script src="vue-router.js"></script>

<div id="app">
    <router-link to='/login' tag='span'>to login</router-link>		//不改 tag 默认 a
    <router-view></router-view>			// 占位符
</div>
<script>
    var login = { template: '<h3>login component<h3>' }
    var routerObj = new VueRouter({
        // mode: 'history',		// 不改默认 hash 模式,改后组件会闪过。。需要开启服务器对 history 的支持
        routes: [
            {path: '/login', component: login}      // 配置路由匹配规则,对应 path 去往对应组件
        ]
    })
    var vm = new Vue({
        el: '#app',
        router: routerObj   // 路由规则对象注册到 vm 上
    })
</script>

// 总结:router-link 的 to 与 routes 里 path 匹配时,才会在 router-view 中显示 component

路由对象的属性

this.$router,全局路由对象

this.$route,当前路由对象

5.2 用户注册案例

用户注册案例

1.   准 备 工 作 1.\ 准备工作 1. 

// login_test 目录下
npm init -y		// 生成 package.json
npm install vue@2.6.x vue-router@3.1.x		// 生成 package-lock.json
npm install webpack@4.39.x webpack-cli@3.3.x webpack-dev-server@3.8.x html-webpack-plugin@3.2.x -D
// -D 表示安装到本地开发依赖 等于 --save-dev	
"dev": "webpack-dev-server --inline --hot --port 8088"
image-20201127230632885
npm install vue-loader@15.7.x vue-template-compiler@2.6.x -D
npm install css-loader@3.2.x style-loader@1.0.x -D
npm install less less-loader -D		// (可不安装) 使用时 <style lang="less/scss/stylus"></style>
npm install sass-loader@7.2.x node-sass@4.12.x -D		// 项目中用到的 安装时出了问题
npm install stylus stylus-loader -D		// (可不安装) 无需配置
npm install url-loader@2.1.x file-loader@4.2.x -D

安装 node-sass 时出现问题

解决网站

npm i node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/

然后成功安装了一个 5.0.0 版本的,根据报错找到这个地方改一下就完事了(问题成功解决.)

image-20201128122937374

接下来安装 MUI,下载后解压出来,然后新建 lib/mui 目录,将 dist 下的 css 和 fonts 目录复制进去

然后在 webpack.config.js 中添加配置,修改了两处:rules 和 plugins

// 新建 webpack.config.js 文件
const htmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')		// vue-loader
module.exports = {
    entry: './main.js',                 // 配置入口文件
    output: {                           // 配置输出文件,设为当前路径,指定文件名
        path: __dirname,
        filename: 'bundle.js'
    },
    resolve: {
        alias: {
            'vue': 'vue/dist/vue.js'    // vue.js 文件路径配置
        }
    },
    devServer: {
        historyApiFallback: true        // 开启服务器对 history 模式支持
    },
    module: {
        rules: [                       // 模块规则
            {
                test: /\.vue$/,
                use: 'vue-loader'
            },
            // more rules
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.less$/,
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            {
                test: /\.scss$/,
                use: ['style-loader', 'css-loader', 'sass-loader']
            },
            {
                test: /\.(jpg|png|gif|bmp|jpeg)$/,
                use: 'url-loader'
            },
            {
                test: /\.(ttf|eot|svg|woff|woff2)$/,
                use: 'url-loader'
            },
        ]
    },
    plugins: [                          // 插件
        new htmlWebpackPlugin({
            template: 'index.html'      // 为 index.html 自动引入打包好的 bundle.js
        }),
        new VueLoaderPlugin()
    ]
}

2.   代 码 实 现 2.\ 代码实现 2. 

// 创建 index.html 首页
<div id="app"></div>

// 创建 main.js 逻辑入口
import Vue from 'vue'
import app from './App.vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import router from './router.js'
import './lib/mui/css/mui.css'

new Vue({
    el: '#app',
    render: c => c(app),
    router
})

// 创建 route.js 一个单独的路由文件
import VueRouter from 'vue-router'
import Login from './components/Login.vue'
import Register from './components/Register.vue'

var router = new VueRouter({
    mode: 'history',				// 后来开 history 模式
    linkActiveClass: 'my-active',
    linkExactActiveClass: 'my-exact-active',	// 这两行是自定义类名 对应 App.vue 导航菜单样式
    routes: [
        {path: '/', redirect: '/login'},
        {path: '/login', component: Login},
        {path: '/register', component: Register}
    ]
})
export default router

// 创建 APP.vue 渲染路由文件
<template>
    <div id="app">
        <div class="login-container">
            <router-link to="/login" tag="span">login</router-link>
            <router-link to="/register" tag="span">register</router-link>
        </div>
        <router-view></router-view>
    </div>
</template>

<style lang='scss' scoped>
    .login-container {
        display: flex;
        justify-content: center;
        padding-top: 10px;
        span {
            padding: 5px 20px;
            border-radius: 5px;
            font-size: 16px;
        }
    }
    .my-active, .my-exact-active {			// 导航菜单样式 对应 router.js 文件里自定义的类名
        background: #007aff;
        font-weight: 800;
        color: #fff;
    }
</style>

// 创建 Login.vue 编写登录界面
<template>
    <div class="login">
        <div class="content">
            
            <form class="mui-input-group login-form">
                <div class="mui-input-row">
                    <label>账号</label>
                    <input type="text" class="mui-input-clear mui-input" placeholder="请输入账号">
                </div>
                <div class="mui-input-row">
                    <label>密码</label>
                    <input type="text" class="mui-input-clear mui-input" placeholder="请输入密码">
                </div>
            </form>
            
            <div class="mui-content-padded">
                <button type="button" class="mui-btn mui-btn-block mui-btn-primary">登录</button>
            </div>
            
        </div>
    </div>
</template>

<script>
    export default {
        data () { return {} }
    }
</script>

<style scoped>
    .login-form {margin: 30px 0; background-color: transparent;}
    .mui-input-group .mui-input-row {margin-bottom: 10px; background: #fff}
    .mui-btn-block {padding: 10px 0;}
</style>

// 创建 Register.vue 编写注册界面
<template>
    <div class="register">
        <div class="content">

            <form class="mui-input-group login-form">
                <div class="mui-input-row">
                    <label>账号</label>
                    <input type="text" class="mui-input-clear mui-input" placeholder="请输入账号">
                </div>
                <div class="mui-input-row">
                    <label>密码</label>
                    <input type="text" class="mui-input-clear mui-input" placeholder="请输入密码">
                </div>
                <div class="mui-input-row">
                    <label>密码确认</label>
                    <input type="text" class="mui-input-clear mui-input" placeholder="请确认密码">
                </div>
                <div class="mui-input-row">
                    <label>邮箱</label>
                    <input type="text" class="mui-input-clear mui-input" placeholder="请输入邮箱">
                </div>
            </form>

            <div class="mui-content-padded">
                <button type="button" class="mui-btn mui-btn-block mui-btn-primary">注册</button>
            </div>

        </div>
    </div>
</template>

<script>
    export default {
        data() { return {} }
    }
</script>

<style scoped>
    .register-form {
        margin: 30px 0;
        background-color: transparent;
    }
    .mui-input-group .mui-input-row {
        margin-bottom: 10px;
        background: #fff;
    }
    .mui-btn-block { padding: 10px 0; }
</style>
// 启动项目
npm run dev

运行成功:

image-20201128123618408

5.3 动态路由

动态路由

如果切换的组件变动不大,只改几个参数,那就没必要销毁再重建组件,用动态路由改参数

使用 query 方式传参,数据以查询字符串的形式显示在地址栏中,不保密(参数在 ? 后)

用 params 方式传参,搭配 history,将参数放在路径中或隐藏

<div id="app">
    <router-link to='/login' tag='span'>to login</router-link>
    <router-view></router-view>

    <router-link to='/user?id=10&name=admin'>Login</router-link>
    <router-view></router-view>

    <router-link to='/user/10/admin'>login</router-link>
    <router-view></router-view>			// 注意,router-view 没设 name 都是 default 视图
</div>

<template id="usertemp">
    <div>
        <h3>id: {{this.$route.query.id}} name: {{$route.query.name}} </h3>
        <h3>id: {{$route.params.id}} name: {{$route.params.name}} </h3>
    </div>
</template>

<script>
    var login = { template: '<h3>login component</h3>' }
    var user = { template: '#usertemp', }
    var router = new VueRouter({
        // mode: 'history',
        routes: [
            {path: '/login', component: login},      // 配置路由匹配规则,对应 path 去往对应组件
            {path: '/user', component: user},
            {path: '/user/:id/:name', component: user}
        ]
    })

    
    var vm = new Vue({
        el: '#app',
        router: router   // 路由规则对象注册到 vm 上,此时可简写为 router
    })
</script>

5.4 嵌套路由

嵌套路由

组件模板里嵌套路由,需要在 children 里列出相应的路由规则

<router-link to='/about' tag='li'>关于公司</router-link>

<template id="about-tmp">
    <div class="about-detail">
        <h1>xxx能力无限公司</h1>
        <router-link to='/about/detail'>公司简介</router-link>
        <router-link to='/about/governance'>公司治理</router-link>
        <router-view></router-view>
    </div>
</template>

// 组件对象
var about = { template: '#about-tmp' }
var detail = { template: '<p>xxx是全球领先的公司</p>'}
var governance = { template: '<p>治理嘛</p>'}

// routes 路由规则
{path: '/', redirect: '/about'},        // 路由重定向,即默认显示
{path: '/about', component: about, children: [
    {path: 'detail', component: detail},
    {path: 'governance', component: governance}
]}		// 就是多个 children 列表

5.5 命名路由 & 命名视图

命名路由

不管路径多长,只要 name 匹配了就行

<router-link :to='{name: "user", params: {id:123}}'>LOGIN</router-link>
{path: '/user/:id', name: 'user', component: user}
// 注意:name 重复会有警告

命名视图

router-view 加个 name,可以分别用来显示组件了,不加默认 name = default

<router-link :to='{name: "user", params: {id:123}}'>LOGIN</router-link>
<router-view></router-view>
<div class="container">
    <router-view name='left'></router-view>
    <router-view name='main'></router-view>
</div>

var header = {template: '<h1 class="header">header</h1>'}
var sidebar = {template: '<h1 class="sidebar">sidebar</h1>'}
var mainBox = {template: '<h1 class="main">mainBox</h1>'}

{path: '/user/:id', name: 'user', component: user},
{path: '/', components: {'default': header, 'left': sidebar, 'main': mainBox}}

5.6编程式导航

编程式导航

就是不用 router-link 进行页面切换(也叫声明式导航)

编程式导航就是直接调用 $router.push() 方法(点击 router-link 就是调用该方法)

<template id="usertemp">
    <div>
        <h3>id: {{this.$route.query.id}} name: {{$route.query.name}} </h3>
        <h3>id: {{$route.params.id}} name: {{$route.params.name}} </h3>
        <p>用户名:{{this.$route.query.name}} </p>
        <p>用户名:{{this.$route.params.name}} </p>
    </div>
</template>

var user = { template: '#usertemp' }

var router = new VueRouter({
    // mode: 'history',
    routes: [
        {path: '/login', component: login},
        {path: '/user', component: user},
        {path: '/user', name: 'user', component: user}
    ]
})

methods: {
    goStart() {
        this.$router.push( { path: '/user', query: {name: 'admin'} } )
        this.$router.push( { name: 'user', params: {name: 'admin'} } )	// 注意 params 与 path 一起用时会被屏蔽
    }
}
test

router.replace & router.go

$router.replace 同 $router.push,不过不向 history 栈中添加记录,就是没有历史,直接替换当前页面

$router.go 就是网页中的前进后退,参数 +x 表示前进 x 页,-x 表示后退 x 页


E n d . End. End.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值