《web前端全栈成长计划》Vue第三章学习笔记(上)
【摘要】 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的区别
源码分析章节略(感觉一来时间进度跟不上,二来难度大。)
(全文完,谢谢阅读)
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
张辉2020/09/08 02:04:411楼编辑删除举报
张辉2020/09/23 10:48:582楼编辑删除举报
《web前端全栈成长计划》Vue第一章学习笔记(上)https://bbs.huaweicloud.com/blogs/196720
《web前端全栈成长计划》Vue第一章学习笔记(下)https://bbs.huaweicloud.com/blogs/196719
《web前端全栈成长计划》Vue第二章学习笔记(上)https://bbs.huaweicloud.com/blogs/196721
《web前端全栈成长计划》Vue第二章学习笔记(下)https://bbs.huaweicloud.com/blogs/196722
《web前端全栈成长计划》Vue第三章学习笔记(上)https://bbs.huaweicloud.com/blogs/196803
(第三章暂时没下,下应该是vue源码分析)
《web前端全栈成长计划》Vue第四章学习笔记(上)https://bbs.huaweicloud.com/blogs/197138
《web前端全栈成长计划》Vue第四章学习笔记(下)https://bbs.huaweicloud.com/blogs/197139
前端小白历险记(一)链接的斜杠怎么没有了?https://bbs.huaweicloud.com/blogs/181124
前端小白历险记(二)原来是你腾讯搞的鬼!https://bbs.huaweicloud.com/blogs/191671
前端小白历险记(三)歪歪扭扭学vue——谈点vue学习时那些不大懂的东西 https://bbs.huaweicloud.com/blogs/197137
前端小白历险记(四)拼死拼活过考核——思想与方法 https://bbs.huaweicloud.com/blogs/197790