前端路由:根据不同的url地址,页面上展示不同的内容(根据url地址的不同分发到不同的组件。)
spa 是
single page application
简写,意思是单页面应用程序。Vue 适合开发 spa 类型的项目。
优点:
缺点:
基于 hash 的路由原理(通过地址栏 hash 字符串的改变,去更新页面的内容)
- http://localhost:3000?username=lisi#abc
- http://localhost:3000?username=lisi#hello
- 锚点 (hash) 作用:跳转到网页的某一个位置
- 锚点的变化不会导致浏览器重新向服务器发送一个请求。
vue-router 是基于 vue 的 js 插件,实现了前端路由功能。
下载地址:https://unpkg.com/vue-router/dist/vue-router.js
Vue Router 3.x 是针对 Vue2 版本的官方路由。
vue 文件分为两类,一个是页面组件,一个是复用组件。
src/views(或pages)
文件夹下的页面组件,配合路由切换。
src/components
文件夹下的一般引入到 src/views
下的 vue 中复用展示数据。
基于 url 地址的变化实现组件的切换。一切都围绕着hash值变化为准。
使用流程:下载路由,编写对应规则注入到vue实例上,使用router-view 挂载点显示切换的路由。
main.js
导入组件时,可以使用 @ 代替 ./
,@的意思是在src文件夹下找文件。
// 引入Router
import VueRouter from 'vue-router'
// 使用路由插件
Vue.use(VueRouter)
// 导入要切换的组件
import Find from './views/Find.vue'
import My from '@views/My.vue'
import Part from '@views/part.vue'
// 创建路由规则数组
const routes = [
{
path: "/find",
component: Find
},
{
path: "/my",
component: My
},
{
path: "/part",
component: Part
}
]
// 创建路由对象,传入规则
const router = new VueRouter({
routes
})
// 关联到Vue实例
new Vue({
router,
})
App.vue
components
换成router-view
,用于组件内容渲染的地方。
<template>
<div>
<div class="footer_wrap">
<a href="#/find">发现音乐a>
<a href="#/my">我的音乐a>
<a href="#/part">朋友a>
div>
<div class="top">
<router-view>router-view>
div>
div>
template>
vue-router 提供了一个全局组件 router-link
router-link
实质上最终会渲染成 a 链接,to 属性等价于提供 href 属性,但是 to 属性不需要加 #
,直接写/组件名
就可以。
router-link
提供了声明式导航高亮的功能(自带类名)
App.vue
<template>
<div>
<div class="footer_wrap">
<router-link to="/find">发现音乐router-link>
<router-link to="/my">我的音乐router-link>
<router-link to="/part">朋友router-link>
div>
<div class="top">
<router-view>router-view>
div>
div>
template>
在跳转路由时,给路由组件对应的组件内传值。
在 router-link
的 to 属性传值:
/path?参数名=值
/pash/
值:需要路由对象提前配置 path: “/pash/参数名”
对应页面组件接收传递过来的值:
$route-query.参数名
$route.params.参数名
有 :
的路径代表要接收具体的值
App.vue
<router-link to="/part?name=小传">朋友-小传router-link>
<router-link to="/part/小智">朋友-小智router-link>
main.js
通过 params 传参,要使用路由定义。
// 创建路由规则数组
const routes = [
{
path: "/part",
component: Part
},
{
path: "/part/:username",
component: Part
}
]
part.vue
<template>
<div>
<p>人名: {{ $route.query.name }} -- {{ $route.params.username }}p>
div>
template>
匹配 path 后,强制切换到目标 path上。
应用场景:当网站需要一个默认页面时,可以将默认页强制重定向到首页。
const routes = [
{
path: "/",
redirect: "/find"
},
]
如果路径 hash 值,没有和数组里的规则匹配,则默认给一个 404 页面。
语法:路由最后,path 匹配 * (任意路径) - 前面不匹配就命中最后这个,显示对应组件页面。
const routes = [
{
path: "*",
component: NotFound
}
]
<router-link to="/404">404router-link>
hash 路由:http://localhost:8080/#/home
history路由:http://localhost:8080/home
(以后上线需要服务器端支持,否则找的是文件夹)
区别:
hash (url中#后面的部分)虽然出现在 URL 中,但不会被包含在 http 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
history 利用了 html5 history interface 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器记录栈
hash 路由 和 history 路由一个加
#
,一个不加#
。
main.js
const router = new VueRouter({
routes,
mode: "history" // 打包上线后需要后台支持, 模式是 hash
})
用 Js 代码跳转。
<template>
<div>
<span @click="goFn('/find')">发现音乐span>
<span @click="goFn('my')">我的音乐span>
<span @click="goFn('part')">朋友span>
div>
template>
<script>
export default {
methods: {
goFn(targetPath) {
this.$router.push({
path: targetPath,
})
}
}
}
script>
多次点同一个按钮,会报错误:避免重复导航到当前位置:“/my”。
解决这个错误,要在 router/index.js 中重写push方法,忽略报错。
// 原来的 push
let originPush = VueRouter.prototype.push;
// 重写push方法
VueRouter.prototype.push = function (location) {
return originPush.call(this, location).catch(err => err);
}
name 属性只有在js才会有用,决定跳转到哪里,其他时候选写。
query需要 path 传值,使用path时,会忽略 params参数。
params 需要 name 传值,name支持query 和 params传参。
this.$router.push({
path: "路由路径",
query: {
"参数名": 值
},
name: "路由名",
params: {
"参数名": 值
}
})
// 对应路由接收参数:$route.params.参数名
// 对应路由接收参数:$route.query.参数名
使用path时,会自动忽略params
My.vue
<template>
<div>
<h1>My Musich1>
<span @click="goFn('find')">发现音乐-编程式导航span>
<br />
<span @click="goQuery">我的音乐-编程式导航queryspan>
<br />
<span @click="goParams">朋友-编程式导航paramsspan>
div>
template>
<script>
export default {
methods: {
goFn(targetPath) {
this.$router.push({
path: targetPath,
})
},
goQuery () {
this.$router.push({
path: 'part',
query: {
name: '小传'
}
})
},
goParams () {
this.$router.push({
path: '/part',
params: {
username: '小智'
}
})
}
}
}
script>
part.vue
<template>
<div>
<h4>{{ $route.query.name }} -- {{ $route.params.username }}h4>
div>
template>
在一级路由下,嵌套二级路由。
思路:
在子组件中新建 router-link
标签,链接二级路由。
在 router/index.js 中的路由规则数组中,给一级路由添加 name 属性和 children 属性。
children 属性中和一级路由一样,有路径 (path) 和 组件 (component)。
语法格式:
const routes = [
// 一级路由1
{
path: '/find',
component: Find,
name: "Find",
children: [
// 二级路由1
{
path: '/find/',
component: Recommend
},
]
}
]
Find.vue
<template>
<div>
<div class="nav_main">
<router-link to="/find/recommend">推荐router-link>
<router-link to="/find/ranking">排行榜router-link>
<router-link to="/find/songlist">歌单router-link>
div>
<div style="1px solid red;">
<router-view>router-view>
div>
div>
template>
<style scoped>
.nav_main {
background-color: red;
color: white;
padding: 10px 0;
}
.nav_main a {
text-align: center;
text-decoration: none;
color: white;
font-size: 12px;
margin: 7px 17px 0;
padding: 0px 15px 2px 15px;
height: 20px;
display: inline-block;
line-height: 20px;
border-radius: 20px;
}
.nav_main a:hover {
background-color: brown;
}
.nav_main .router-link-active {
background-color: brown;
}
style>
router/index.js
路由规则数组在一级路由下写 children 属性,代表当前的二级路由。
const routes = [
{
path: "/find",
component: Find,
// 二级路由
name: "Find",
children: [
{
path: "recommend",
component: Recommend
},
{
path: "ranking",
component: Ranking
},
{
path: "songlist",
component: SongList
}
]
},
// 404: 只需要在一级栏里给一个全局使用
{
path: "*",
component: NotFound
},
]
路由跳转之前,先执行前置守卫函数,判断是否可以正常跳转。
语法格式:
router.beforeEach((to, from, next) => {
if (to.path == '目标页面' && 登录状态 == false) {
// 未登录执行代码块。
next(false); // 阻止跳转
} else {
next(); // 已登录,放行
}
})
属性:
- to:要跳转的路由。
- from:从哪里跳转的路由。
- next:函数体。
应用场景:在跳转路由之前,判断用户是否登录,为登录弹窗提示,登录后跳转到 我的音乐 页面。
const router = new VueRouter({
routes,
})
// 模拟登录状态
let isLogin = false;
router.beforeEach((to, from, next) => {
if (to.path == '/find' && isLogin == false) {
alert('请登录');
next(false); // 阻止跳转
} else {
next(); // 放行
}
})
vant 是一个轻量、可靠的移动端Vue组件库,开箱即用。
官网地址:https://vant-contrib.gitee.io/vant/#/zh-CN/
特点:
Vant 支持一次性导入所有组件,引入所有组件会增加代码包体积,不推荐。
下载 vant 组件
yarn add vant -D
导入所有组件,到 main.js 中
import Vue from 'vue';
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
使用按钮组件
https://vant-contrib.gitee.io/vant/#/zh-CN/button
<van-button type="primary">主要按钮van-button>
<van-button type="info">信息按钮van-button>
<van-button type="default">默认按钮van-button>
<van-button type="warning">警告按钮van-button>
<van-button type="danger">危险按钮van-button>
只引入使用的组件。
在不使用插件的情况下,可以手动引入需要的组件。
手动单独引入,快速开始:https://vant-contrib.gitee.io/vant/#/zh-CN/quickstart
import Button from 'vant/lib/button'; // button 组件
import 'vant/lib/button/style'; // button 样式
注册
components: {
VanButton: Button // 手动注册组件名
[Button.name]: Button // 等价的
}
使用
<van-button type="primary">主要按钮van-button>
<van-button type="info">信息按钮van-button>
<van-button type="default">默认按钮van-button>
<van-button type="warning">警告按钮van-button>
<van-button type="danger">危险按钮van-button>
按需求加载组件。
babel-plugin-import
是一款 babel 插件,他会在编译过程中将import 的写法自动转换为按需求引入的方式。
安装插件
yarn add babel-plugin-import -D
在 babel 配置文件里 (babel.config.js)
module.exports = {
plugins: [
['import', {
libraryName: 'Vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
}
全局注册 (main.js)
import Vue from 'vue'
import 'vant/lib/index.css'
import { Button } from 'vant'
Vue.use(Button);
弹出模态框,常用于消息提示、消息确认,或在当前页面内完成特定的交互操作。
https://vant-contrib.gitee.io/vant/#/zh-CN/dialog
<template>
<div>
<van-button type="primary" @click="btn">提示弹窗van-button>
div>
template>
<script>
// 导入提示弹窗
import { Dialog } from "vant";
export default {
methods: {
btn() {
// 属性
Dialog({
title: '标题',
message: "提示",
showCancelButton: true
});
},
}
};
script>
Dialog 是一个函数,调用后会直接在页面中弹出相应的模态框。
Dialog 是一个方法,要在需要使用的组件中导入,不可以在 main.js 中导入。
Dialog.confirm()
Dialog.alert()
用于数据录入、校验,支持输入框、单选框、复选框、文件上传等类型,需要与 Field 输入框 组件搭配使用。2.5 版本开始支持此组件。
https://vant-contrib.gitee.io/vant/#/zh-CN/form
import { Form, Field } from 'vant'
Vue.use(Form);
Vue.use(Field);
通过 rules
定义表单校验规则。
键名 | 说明 | 类型 |
---|---|---|
required | 是否为必选字段 | boolean |
message v2.5.3 |
错误提示文案 | string | (value, rule) => string |
validator v2.5.3 |
通过函数进行校验 | (value, rule) => boolean | Promise |
pattern v2.5.3 |
通过正则表达式进行校验 | RegExp |
trigger v2.5.2 |
本项规则的触发时机,可选值为 onChange 、onBlur |
string |
formatter v2.5.3 |
格式化函数,将表单项的值转换后进行校验 | (value, rule) => any |
登录框
<van-form @submit="onSubmit">
<van-field
v-model="username"
name="username"
label="username"
placeholder="用户名"
:rules="[{ required: true, message: '请填写用户名' }]"
/>
<van-field
v-model="password"
type="password"
name="password"
label="password"
placeholder="密码"
:rules="[{ required: true, message: '请填写密码' }]"
/>
<div style="margin: 16px;">
<van-button round block type="info" native-type="submit">
提交
van-button>
div>
van-form>
<script>
export default {
data() {
return {
username: '',
password: '',
};
},
methods: {
onSubmit(values) {
console.log('submit', values);
},
},
};
script>
端口不一样,
反向代理解决跨域
本地 node 服务器开启 cors,负责请求的转发和数据接收回传。