- A+
Vue-router路由
什么是vue-router?
服务端路由指的是服务器根据用户访问的 URL 路径返回不同的响应结果。当我们在一个传统的服务端渲染的 web 应用中点击一个链接时,浏览器会从服务端获得全新的 HTML,然后重新加载整个页面。
然而,在单页面应用中,客户端的 JavaScript 可以拦截页面的跳转请求,动态获取新的数据,然后在无需重新加载的情况下更新当前页面。这样通常可以带来更顺滑的用户体验,尤其是在更偏向“应用”的场景下,因为这类场景下用户通常会在很长的一段时间中做出多次交互。
在这类单页应用中,“路由”是在客户端执行的。一个客户端路由器的职责就是利用诸如 History API 或是 hashchange
事件这样的浏览器 API 来管理应用当前应该渲染的视图。
简单来说,vue-router实现的是一个页面,且页面不变,只是内容在改变,由于页面是由一个一个的组件堆积起来的,所以,vue-router不用改变页面,它只需要将页面内的组件更换就可以了,对于单个页面来讲,可以有很高的复用性,我们只需要关注组件的开发,前端的页面永远不会改,改变的只是路由引入的一个个组件。
安装vue-router
如果一开始你是使用 npm init 命令来初始化的myvue项目,则是使用
npm install vue-router --save-dev
如果使用的是cnpm init初始化的,则使用
cnpm install vue-router --save-dev
注意下载一定要在myvue项目下,或者你初始化的那个项目名路径下,一定不要随便一个路径就安装
工程化模块的使用
在使用一个模块化工程的时候,必须要通过Vue.use()明确的安装路由功能
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter);
import VueRouter from 'vue-router'
vue-router:就是刚刚下载的那个router,在此js文件下,使用VueRouter来代替它 这句话和Java的new关键字很像
VueRouter:在此js文件下使用这个名字来完成路由的功能,vue-router的功能被映射到VueRouter的身上了
Vue.use():此方法在引入官方的模块工程后有,就好比Java的显式声明,无声明是使用不了这个工程化模块的
Vue-router测试
第一步:优化初始化项目
在使用 vue init webpack myvue一个项目后,其中很多的都是官方自带了,我们需要的是一个干净的项目,所以需要删除其它的文件
比如:assets包下全部删除,components包下全部删除
第二步:编写一个自定义组件Content.vue和main.vue
组件的位置都是放在componemts包下的,我们上一步已经清理了此包,所以应该只有新建的这个组件
代码内容:
<!--conten.vue--> <template> <div id="di1"> <h1>此是内容页</h1> <h2>且它位于Content组件中</h2> </div> </template> <script> export default { name: "Content" } </script> <style scoped> #di1{ width: 200px; height: 80px; border: 2px solid blue; border-radius: 50px; margin: 10px auto; } h1{ color: aqua; } </style> <!--main.vue--> <template> <div id="di1"> <h1>此是主页页</h1> <h2>且它位于main组件中</h2> </div> </template> <script> export default { name: "main" } </script> <style scoped> #di1{ width: 200px; height: 80px; border: 2px solid red; border-radius: 50px; margin: 20px auto; } h1{ color: #8c4949; } </style>
第三步:在src建立route目录
在此目录建立index.js,用于建立路由路径指向
代码展示:
import Vue from "vue"; // 导入路由插件 import Router from 'vue-router'; //导入自定义定义的组件 import Content from "../components/Content"; import main from "../components/main"; Vue.use(Router); //配置路由 export default new Router({ routes: [ { //路由路径 path: '/content', //路由名称 name: 'context', //跳转到的组件 component: Content }, { //路由路径 path: '/main', //路由名称 name: 'main', //跳转到的组件 component: main } ] });
第四步:在main.js下引入路由属性
代码展示:
import Vue from 'vue' import App from './App' // 导入自定义的路由条目 import router from "./router"; //关闭生产模式给出的提示 Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', //配置路由,引入路由属性 router, components: { App }, template: '<App/>' })
第五步:在App.vue中使用
使用此模板一定要注意配置,这是首页,展示这块就需要在这里搭建模板
代码展示:
<template> <div id="app"> <h1>Vur-Router</h1> <router-link to="/main">首页</router-link> <router-link to="/content">内容页</router-link> <!-- 请求到组件--> <router-view></router-view> <!-- 显示组件--> </div> </template> <script> export default { name: 'App', } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
第六步:使用路由
使用以下命令打包web
npm run dev
如果打包不成功,但是前面第一个初始项目是可以跑起来的话,很可能是vue-route版本不匹配,可以网上搜索vue-cil ,npm ,vue-route三个的版本区间
我这里使用的是vue-router@3.5版本是可以打包的
//先卸载以前的版本 npm uninstall vue-router //安装.5 npm install vue-router@3.5.2
如果还不行,可以自己去搜索三者版本推荐,或者参考下方:
- Vue CLI 4.5以下,对应的是Vue2;
- Vue CLI 4.5及以上,对应的是Vue3,也可以手动选择Vue2 vue;
- 3.0以下兼容的是element-ui前端组件库;
- vue 3.0兼容的是element-plus前端组件库;
- vue2搭配vue-router3;
- vue3搭配vue-router4
ElementUI - Vue组合开发
elementUI地址:https://element.eleme.cn/#/zh-CN/component/layout
准备工作:
使用windos命令行准备
初始化一个项目:
vue init webpack hello-vue
进入新的目录:
cd hello-vue
安装vue-router
//国外镜像 npm install vue-router --save-dev //国内淘宝镜像 cnpm install vue-router --save-dev
安装elementUI
//国外镜像 npm i elemnet-ui -S //国内镜像 cnpm i elemnet-ui -S
安装vue环境依赖
//国外镜像 npm install //国内镜像 cnpm install
启动测试
npm run dev
部分npm命令解释
- npm install moduleName :安装模块到项目下
- npm install -g moduleName:-g 是将模块安装到全局,具体安装到那个位置,还需要看npm config prefix的位置
- npm install --save moduleName:--save是安装模块到项目目录下,并在package文件的dependencies写入依赖,-S为此命令的缩写
- npm install --save-dev moduleName:--save-dev的意思是将模块安装到项目目录下,并在package文件的devDependencies结点写入依赖,-D为此命令的缩写
实施组合开发
项目结构简介:
- assets:用于存放资源文件
- components:用于存放Vue功能组件
- views:用于存放Vue视图组件
- router:用于存放vue-router配置
确保项目中一开始就创建了以上目录
第一步:在views目录下,创建一个名为Main.vue的视图组件
代码展示:
<template> <div id="di"> <h1> 这是首页</h1> </div> </template> <script> export default { name: "main" } </script> <style scoped> #di{ width: 400px; height: 300px; color: aqua; border: 2px solid blue; border-radius: 50px; margin: 0 auto; } </style>
第二步:在views目录下,继续创建一个Login.vue的视图组件
此组件可以导入一些ElementUI的组件,其中el-*就是element组件的标识
代码展示:
<template> <el-form :model="dynamicValidateForm" ref="dynamicValidateForm" label-width="100px" class="demo-dynamic"> <el-form-item prop="email" label="邮箱" :rules="[ { required: true, message: '请输入邮箱地址', trigger: 'blur' }, { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] } ]" > <el-input v-model="dynamicValidateForm.email"></el-input> </el-form-item> <el-form-item v-for="(domain, index) in dynamicValidateForm.domains" :label="'域名' + index" :key="domain.key" :prop="'domains.' + index + '.value'" :rules="{ required: true, message: '域名不能为空', trigger: 'blur' }" > <el-input v-model="domain.value"></el-input><el-button @click.prevent="removeDomain(domain)">删除</el-button> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('dynamicValidateForm')">提交</el-button> <el-button @click="addDomain">新增域名</el-button> <el-button @click="resetForm('dynamicValidateForm')">重置</el-button> </el-form-item> </el-form> </template> <script> export default { data() { return { dynamicValidateForm: { domains: [{ value: '' }], email: '' } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); this.$route.push("/main"); return true; } else { console.log('error submit!!'); return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); }, removeDomain(item) { var index = this.dynamicValidateForm.domains.indexOf(item) if (index !== -1) { this.dynamicValidateForm.domains.splice(index, 1) } }, addDomain() { this.dynamicValidateForm.domains.push({ value: '', key: Date.now() }); } } } </script>
第三步:在router目录下,新建index.js编写路由指向
代码展示:
import Vue from 'vue'; import Router from 'vue-router'; import Login from "../views/Login.vue"; import Main from "../views/main.vue"; Vue.use(Router); export default new Router({ routes: [ { //登录项 path: '/login', name: 'login', component: Login }, { path: '/main', name: 'main', component: Main } ] });
第四步:在mian.js中配置路由属性,并配置ElementUI
在main.js中配置的是启动项,像路由和elementUI都是需要导入的,不然是找不到属性的
代码展示:
import Vue from 'vue' import router from "./router"; Vue.config.productionTip = false import ElementUI from 'element-ui'; //导入ElementUI import 'element-ui/lib/theme-chalk/index.css';//使用ElementUI的css库 import App from './App.vue'; Vue.use(ElementUI); //导入,使用Vue.use方法使用后,才能配置属性 Vue.use(router); new Vue({ el: '#app', router,//配置路由属性 render: h => h(App) //配置elementUI属性,这是elemenUI官网的写法,详情参照官网 });
第五步:编写App.vue组件
此组件是main.js的组件,也是index.html第一就会加载的组件,所以需要考虑的是项目初次进入应该展示什么
这里测试项目可以不用展示,主要是展示其它组件,所以我只留下了<router-view>标签,用于在请求到其它组件时呈现此组件
代码展示:
<template> <div id="app"> <router-view></router-view> <!-- 组件内容展示,通过改变地址栏请求,获取组件:/login;/main--> </div> </template> <script> export default { name: 'App', } </script> <style> </style>
第六步:打包,测试
使用一下命令:
npm run dev
注意:如果打包失败,最大的可能是版本不兼容,也就是:sass-loader 版本过高了,需要降低版本
在package.json文件中,找到"sass-loader": "^13.3.2" 这一项,更改后面^13.3.2为^8.0.0或者^7.3.1
在使用一些命令重新更新环境
//初始化使用 npm 初始的环境 npm install //初始化使用cnpm初始的环境 cnpm install
如果还是打包失败,请上百度搜索
Vue路由嵌套
嵌套路由,又称子路由,在实际引用中,通常使用多个嵌套的组件构成的,同样的,URL中各种动态路径也按照某种结构对应嵌套的各层组件
使用嵌套路由的好处是,子路由的父级路由组件依旧可以存在,在不使用嵌套路由的情况下,默认只会在当前路由中的组件,换言之,如果在此页面上,你想显示多个组件,但是它们有分布在不同的vue模块中,就可以使用嵌套路由
嵌套路由虽然可以使多个组件同时存在于页面上,但是一定要处理每个子路由组件的位置,不然页面会很难看
嵌套路由配置的关键字:
export default new Router({ routes: [ { //登录项 path: '/login', name: 'login', component: Login }, { path: '/main', name: 'main', component: Main, children: [ //嵌套路由,它们会在mian.vue组件下,继续显示 { path:'/user', name: 'user', component: user }, { path:'/nav', name: 'nav', component: navigation } ] } ] });
children关键字就是配置嵌套路由的,它可以使得父组件和子组件在同一页面同时显示
main.vue组件构建
代码展示:
<template> <div> <el-container> <el-aside width="200px"> <el-menu :default-openeds="['1']"> <el-submenu index="1"> <template slot="title"><i class="el-icon-caret-right"></i>用户管理</template> <el-menu-item-group> <el-menu-item index="1-1"> <router-link to="/user">个人信息</router-link><!--呼出,子路由1 user组件--> </el-menu-item> <el-menu-item index="1-2"> <router-link to="/nav">用户列表</router-link><!--呼出,子路由2 navigation组件--> </el-menu-item> </el-menu-item-group> </el-submenu> <el-submenu index="2"> <template slot="title"><i class="el-icon-caret-right"></i>内容管理</template> <el-menu-item-group> <el-menu-item index="2-1">分类管理</el-menu-item> <el-menu-item index="2-2">内容列表</el-menu-item> </el-menu-item-group> </el-submenu> </el-menu> </el-aside> <el-container> <el-header style="text-align: right; font-size: 12px;"> <el-dropdown> <i class="el-icon-setting" style="margin-right: 15px;"></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>个人信息</el-dropdown-item> <el-dropdown-item>退出登陆</el-dropdown-item> </el-dropdown-menu> </el-dropdown> </el-header> <el-main> <router-view/> <!-- 子路由出现的位置,也是其组件内容摆放的地方 --> </el-main> </el-container> </el-container> </div> </template> <script> export default { name:"main" } </script>
被注释的地方就是嵌套路由的设置地方
由于使用的elementUI组件,所以自己的配置相对来说就很少了
路由参数传递及重定向
参数传递需要更改三个地方:
- 传递参数的组件:需要定义参数名,以及使用v-bind绑定一个对象,有参数后 to 后面就不知一个地址了,还有参数,所以是一个对象,需要v-bind绑定,参数属性,params
- 路由文件配置:需要在接收路由上配置结构参数名,使用字符串拼接 /:参数名,并开启可以接收参数的开关,props:true
- 接收参数的组件:在<script>标签中,配置props:[ ' 接收参数名' ]
注意:参数传递都是route模块在做,所以传递的时候会在<router-link>标签内
传递参数的组件
<router-link v-bind:to="{name:'user',params:{id:1}}">个人信息</router-link>
name属性:参数要去的组件名或者路径
params:参数对象,以key:value的形式存在,传递参数的变量,可以传送多个
路由文件配置
{ path:'/user/:id', name: 'user', component: user, props: true }
在路径上要进行字符串拼接,同步传输路径 /:id ,传递参数为 id
props: true ,允许此组件接收参数
接收参数的组件
<template> <diV> <h1>用户名单</h1> <h1>用户ID:{{id}}</h1> </diV> </template> <script> export default { props: ['id'], name: "user" } </script>
props:[ 'id'] ,接收参数
{{id}} :取参数
重定向redirect
这个配置也是写在路由配置中的,和正常的条目是一样书写的,只是内部的属性不一样
{ path: '/goMain', redirect: '/main' }
path:请求重定向的路径,此路径被点击后便可以触发重定向
redirect:重定向到哪里去,后面跟重定向的新地址
拓展:重定向和转发的区别
- 重定向地址栏会发生改变,重定向到新的地址
- 转发地址栏不会改变,转发请求