《web前端全栈成长计划》Vue第三章学习笔记(上)
本文摘自 论坛 https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=71831&authorid=70062&page=1 笔者对vue学习的笔记。由于vue笔者也是刚刚接触,基本上都是以观看视频和具体动手实践的方式进行。为防止迷路,特收集整理成本博文。
文中的图片、代码很多来自于教程本身,但都来自于本人实践后截图和拷贝的结果,特此说明。
Vue 第三章 Vue路由
38 UI组件库 mint-ui
都是饿了吗出的
Mint UI 移动端 http://mint-ui.github.io/
Element PC端
38.1 Mint UI
38.1.1 安装
npm install --save mint-ui
38.1.2 实现按需打包:
npm install --save-dev babel-plugin-component
配置.babelrc
"plugins": ["transform-vue-jsx", "transform-runtime",["component", [ { "libraryName": "mint-ui", "style": true } ]]]
移动端需要引入fastclick,解决事件延迟问题,实现快速点击。
38.1.3 范例:
main.js引入mint
import {Button} from 'mint-ui' // 注册成标签 // 以前在components中注册。 // 现在可以做全局注册 默认用mint预定好的名字 Vue.component(Button.name, Button)
App.vue定义button并使用:
<template> <mt-button type="primary" @click.native="handleClick" style="width:100%" >按钮</mt-button> </template> <script> import {Toast} from 'mint-ui' export default { methods: { handleClick () { Toast('Notice Message') } } } </script>
38.1.4 实际效果:
大多数组件可以找到,解决很多实际的移动端UI开发问题。
具体需要开发者一一去尝试。
39 路由介绍
39.1 目标
39.2 分析:
SPA 单页应用
路由链接
点击路由链接,不向后台发请求,而是显示不同的路由组件。而不同的路由组件会在操作中向后台发请求。
路由插件:vue-router
39.3 下载并安装包:
npm install vue-router --save
39.4 概念:
路由器:管理路由。
什么是路由:是个映射关系。
后台路由 Key=Path,Value=(处理请求的回调函数)
前台路由 Key=Path , Value = 组件
在vueRouter里面暴露的是创建路由器的构造函数。
new VueRouter({
//
})
路由配置:数组,数组中的每个值都是对象
routes:[
{ //一般路由
path: '/about',
comonent: About
},
{ //自动跳转路由
path: '/',
redirect: '/about'
},
...
]
先需要配置路由器:
import router from './router'
new Vue({
router
})
此后的路由才能访问
路由链接:
<router-link> 生成路由链接
<router-view> 显示当前路由组件
40 基本路由
40.1 目标
非路由组件放入components目录里
路由组件一般放入views或者pages目录
40.2 实践(具体步骤)
在views下定义好路由组件
在router的index.js中,将路由组件映射成路由
在某个(App.vue)组件中去写两种标签 router-link和router-view
选择了哪个,router-link-active就在哪个上面有。那么,只要给这个类名加样式,就可以把当前路由页面设置颜色。
views/About.vue
<template> <div> About </div> </template> <script> export default {} </script> <style> </style>
views/Home.vue
<template> <div> Home </div> </template> <script> export default {} </script> <style> </style>
router/index.js
/* 路由器模块 */ import Vue from 'vue' import VueRouter from 'vue-router' import About from '../views/About' import Home from '../views/Home' Vue.use(VueRouter) // 默认暴露 export default new VueRouter({ // 配置N个路由 routes: [ { path: '/about', component: About }, { path: '/home', component: Home }, { path: '/', redirect: '/about' } ] })
App.vue
<template> <div> <div class="row"> <div class="col-xs-offset-2 col-xs-8"> <div class="page-header"> Router Basic - 01 </div> </div> </div> <div class="row"> <div class="col-xs-2 col-xs-offset-2"> <div class="list-group"> <router-link to="/about" class="list-group-item">About</router-link> <router-link to="/home" class="list-group-item">Home</router-link> </div> </div> <div class="col-xs-6"> <div class="panel"> <div class="panel-body"> <router-view></router-view> </div> </div> </div> </div> </div> </template> <script> export default { } </script> <style> </style>
main.js
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' /* 注意大小写 */ import App from './App' import router from './router' // 配置对象的属性都是固定的属性名,不能随便修改 new Vue({ el: '#app', components: { App }, template: '<App/>', router // 路由器配置 })
index.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="stylesheet" href="./static/css/bootstrap.css"> <title>vue_demo</title> <style> .router-link-active { color: red !important; } </style> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
40.3 演示效果:
40.4 配置优化:
liveActiveClass: 'active', //指定选中的路由链接的class
40.4 总结
编写路由三步:
定义路由组件
注册路由
使用路由 <router-link> <router-view>
41 嵌套路由
41.1 目标:
41.2 分析:
将上面简单路由的Home组件改为 News和Message两个组件。。
其中News下面是个数组,元素为单个文本。Message也是个数组,其元素是个对象{},有链接,有消息内容,还有消息id
41.3 实践(具体步骤)
在上例代码中修改:
views下新增News.vue
<template> <div> <ul> <li v-for="(news,index) in newsArr" :key="index">{{news}} </ul> </div> </template> <script> export default { data () { return { // 根据效果去设计数据结构 newsArr: [ 'news001', 'news002', 'news003', 'news004' ] } } } </script> <style> </style>
views下新增Messages.vue
<template> <ul> <li v-for="(message, index) in messages" :key="message.id"> <a href="??">{{message.title}}</a> </ul> </template> <script> export default { data () { return { // 根据效果去设计数据结构 messages: [ ] } }, mounted () { // 模拟ajax请求从后台获取数据 // 回调函数用箭头函数 setTimeout(() => { const messages = [ { id: 1, title: 'message001' }, { id: 2, title: 'message002' }, { id: 4, title: 'message004' } ] this.messages = messages }, 1000) } } </script> <style> </style>
更新路由配置 router/index.js
/* 路由器模块 */ import Vue from 'vue' import VueRouter from 'vue-router' import About from '../views/About' import Home from '../views/Home' import News from '../views/News' import Message from '../views/Message' Vue.use(VueRouter) // 默认暴露 export default new VueRouter({ // 配置N个路由 routes: [ { path: '/about', component: About }, { path: '/home', component: Home, children: [ { path: '/home/news', component: News }, { // 简化写法,相对于home path: 'message', component: Message }, { // 定义home的缺省页面 path: '', redirect: '/home/news' } ] }, { path: '/', redirect: '/about' } ] })
41.4 演示效果:
点击Message后:
42 缓存路由
42.1 目标:
切换走了,再切换回来,希望数据还在。
42.2 分析:
现在不在了:说明当前About是新的。如果要求数据还在,就必须是个老的。
旧的路由组件啥时死了?——被切换时。
再切换回来时,重新创建。
43.3 做法:
增加keep-alive标签
43.4 应用场景:
很广泛,主要是不同的tab页有很多输入项,切换后,原来的输入项要保留。
但是,如果数据实时要求性高,要反复从后台读取数据时,应不做缓存
43.5 实现:
App.vue给route-view标签增加以下处理
<keep-alive> <router-view msg="abc"></router-view> </keep-alive>
43.6 演示效果:
about输入值:
切换到其他地方:
再切换回来:
可以发现,刚才录入的数据还在。
43 向路由组件传递数据
43.1 目标:
点击上面的message01 ,弹出下面的内容
43.2 分析:
新增MessageDetail 页面
将MessageDetail映射成组件
$route代表当前路由
$route.params.id
43.3 实践:
43.3.1 向路由组件传递数据:路径携带参数params。(方式1)
views/Message.vue
<template> <div> <ul> <li v-for="(message, index) in messages" :key="message.id"> <!--<a href="??">{{message.title}}</a> ES5的语法,使用单引号‘ ES6的语法:使用反单引号` --> <router-link :to="`/home/message/detail/${message.id}`">{{message.title}}</router-link> </ul> <hr> <router-view></router-view> </div> </template> <script> // 请求参数两种: // Param参数 ? // Query参数 export default { data () { return { // 根据效果去设计数据结构 messages: [ ] } }, mounted () { // 模拟ajax请求从后台获取数据 // 回调函数用箭头函数 setTimeout(() => { const messages = [ { id: 1, title: 'message001' }, { id: 2, title: 'message002' }, { id: 4, title: 'message004' } ] this.messages = messages }, 1000) } } </script> <style> </style>
views/MessageDetail.vue
<template> <div> ID:{{$route.params.id}} <ul> id: {{messageDetail.id}} title: {{messageDetail.title}} content: {{messageDetail.content}} </ul> </div> </template> <script> export default { data () { return { messageDetail: {} } }, mounted () { setTimeout( () => { const allMessageDetails = [ { id: 1, title: 'message001', content: 'message001 content...' }, { id: 2, title: 'message002', content: 'message002 content...' }, { id: 3, title: 'message003', content: 'message003 content...' }, { id: 4, title: 'message004', content: 'message004 content...' } ] this.allMessageDetails = allMessageDetails // 过滤产生的数据还是数组 // 乘以1表示id为数字 const id = this.$route.params.id * 1 this.messageDetail = allMessageDetails.find(detail => detail.id === id) },1000) }, //需要监视 watch: { $route: function (value) { // 路由路径(param)发生了改变 const id = value.params.id * 1 this.messageDetail = this.allMessageDetails.find(detail => detail.id === id) } } } </script> <style> </style>
router/index.js
/* 路由器模块 */ import Vue from 'vue' import VueRouter from 'vue-router' import About from '../views/About' import Home from '../views/Home' import News from '../views/News' import Message from '../views/Message' import MessageDetail from '../views/MessageDetail' Vue.use(VueRouter) // 默认暴露 export default new VueRouter({ // 配置N个路由 routes: [ { path: '/about', component: About }, { path: '/home', component: Home, children: [ { path: '/home/news', component: News }, { // 简化写法,相对于home path: 'message', component: Message, children: [ { path: '/home/message/detail/:id', // 使用占位语法 component: MessageDetail } ] }, { // 定义home的缺省页面 path: '', redirect: '/home/news' } ] }, { path: '/', redirect: '/about' } ] })
实际效果:
43.3.2 向路由组件传递数据:query参数(方式2)。
修改方式:
router/index.js 去掉id
children: [ { path: '/home/message/detail', // 使用占位语法 component: MessageDetail } ]
views/Message.vue 将to改为 ?id=...
<template> <div> <ul> <li v-for="(message, index) in messages" :key="message.id"> <!--<a href="??">{{message.title}}</a> ES5的语法,使用单引号‘ ES6的语法:使用反单引号` --> <router-link :to="`/home/message/detail?id=${message.id}`">{{message.title}}</router-link> </ul> <hr> <router-view></router-view> </div> </template>
views/MessageDetail.vue 将原来的params.id 改为 query.id
<template> <div> ID:{{$route.query.id}} <ul> id: {{messageDetail.id}} title: {{messageDetail.title}} content: {{messageDetail.content}} </ul> </div> </template> <script> export default { data () { return { messageDetail: {} } }, mounted () { setTimeout( () => { const allMessageDetails = [ { id: 1, title: 'message001', content: 'message001 content...' }, { id: 2, title: 'message002', content: 'message002 content...' }, { id: 3, title: 'message003', content: 'message003 content...' }, { id: 4, title: 'message004', content: 'message004 content...' } ] this.allMessageDetails = allMessageDetails // 过滤产生的数据还是数组 // 乘以1表示id为数字 const id = this.$route.query.id * 1 this.messageDetail = allMessageDetails.find(detail => detail.id === id) },1000) }, //需要监视 watch: { $route: function (value) { // 路由路径(param)发生了改变 const id = value.query.id * 1 this.messageDetail = this.allMessageDetails.find(detail => detail.id === id) } } } </script> <style> </style>
实际效果:
跟原来一致。
43.3.3 向路由组件传递数据:route-view属性携带数据(方式3)。
<route-view :msg="msg"><route-view>
其实用法跟props类似
组件通过特定的标签route-view来显示的。
如果App.cue想向Home.vue和About.vue传递数据。可以在router-view传。
App.vue
<router-view msg="abc"></router-view>
About.vue
在export中声明从App引入的属性
在模板中引用该msg
<template> <div> About {{msg}} <input type="text"> </div> </template> <script> export default { // 需要从App接收msg属性,先要声明 props: { msg: String } } </script> <style> </style>
实际效果:
可见msg已被传输到About
44 编程式路由导航
44.1 概念
什么叫做编程式?
从A页面跳转到B页面有两种做法:
<a>标签,直接跳转
加监听,通过js的方式实现页面跳转
编程式路由导航:通过js代码实现路由的跳转
44.2 目标:
44.3 实践1:
App.vue
<template> <div> <div class="row"> <div class="col-xs-offset-2 col-xs-8"> <div class="page-header"> Router Basic - 01 </div> </div> </div> <div class="row"> <div class="col-xs-2 col-xs-offset-2"> <div class="list-group"> <router-link to="/about" class="list-group-item">About</router-link> <router-link to="/home" class="list-group-item">Home</router-link> </div> </div> <div class="col-xs-6"> <div class="panel"> <div class="panel-body"> <keep-alive> <router-view msg="abc"></router-view> </keep-alive> </div> </div> </div> </div> </div> </template> <script> export default { } </script> <style> </style>
views/Message.vue
<template> <div> <ul> <li v-for="(message, index) in messages" :key="message.id"> <!--<a href="??">{{message.title}}</a> ES5的语法,使用单引号‘ ES6的语法:使用反单引号` --> <router-link :to="`/home/message/detail/${message.id}`">{{message.title}}</router-link> <button @click="pushShow(message.id)">push查看</button> <button @click="replaceShow(message.id)">replace查看</button> </ul> <hr> <router-view></router-view> </div> </template> <script> // 请求参数两种: // Param参数 ? // Query参数 export default { data () { return { // 根据效果去设计数据结构 messages: [ ] } }, mounted () { // 模拟ajax请求从后台获取数据 // 回调函数用箭头函数 setTimeout(() => { const messages = [ { id: 1, title: 'message001' }, { id: 2, title: 'message002' }, { id: 4, title: 'message004' } ] this.messages = messages }, 1000) }, methods: { pushShow (id) { this.$router.push(`/home/message/detail/${id}`) }, replaceShow (id) { this.$router.replace(`/home/message/detail/${id}`) } } } </script> <style> </style>
views/MessageDetail.vue
<template> <div> ID:{{$route.params.id}} <ul> id: {{messageDetail.id}} title: {{messageDetail.title}} content: {{messageDetail.content}} </ul> </div> </template> <script> export default { data () { return { messageDetail: {} } }, mounted () { setTimeout( () => { const allMessageDetails = [ { id: 1, title: 'message001', content: 'message001 content...' }, { id: 2, title: 'message002', content: 'message002 content...' }, { id: 3, title: 'message003', content: 'message003 content...' }, { id: 4, title: 'message004', content: 'message004 content...' } ] this.allMessageDetails = allMessageDetails // 过滤产生的数据还是数组 // 乘以1表示id为数字 const id = this.$route.params.id * 1 this.messageDetail = allMessageDetails.find(detail => detail.id === id) },1000) }, //需要监视 watch: { $route: function (value) { // 路由路径(param)发生了改变 const id = value.params.id * 1 this.messageDetail = this.allMessageDetails.find(detail => detail.id === id) } } } </script> <style> </style>
比较下push和replace的差异
push
先访问news
再访问message
push detail 1
点击back--》应看到message
replace
先访问news
再访问message
replace detail 1
点击back=》应看到news
实际效果:
因点击的过程太多,不便演示。暂时截个主图。效果其实跟前面提到的是一致的。
44.3 实践2:
目标及处理:
通过编码的方式也要实现回退
Message.vue增加以下内容:
<button @click="$router.back()">回退</button>
效果如下:
这种场景经常见到。
44.4 总结:
$router.push(path) 点击路由链接(可以返回)
$router.replace(path) 新路由替换老路由(不可以返回)
$router.go(-1) 后退 等同于 $router.back()
$router.go(1) 前进
注意 $route和$router的区别
源码分析章节略(感觉一来时间进度跟不上,二来难度大。)
(全文完,谢谢阅读)
- 点赞
- 收藏
- 关注作者
评论(0)