(zichao)VUE2基础_2(仅作简单整理,未深入探究)
目录
一、使用Vue脚手架
(一)说明
- Vue 脚手架是 Vue 官方提供的标准化开发工具(开发平台)。
- 最新的版本是 4.x。
- 文档: https://cli.vuejs.org/zh/。
(二)具体步骤
- (仅第一次执行):全局安装@vue/cli。
npm install -g @vue/cli
- 切换到你要创建项目的目录,然后使用命令创建项目
vue create xxxx
- 启动项目
npm run ***.js
(三)模板项目的结构
── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── component: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ │── main.js: 入口文件
├──.gitignore: git 版本管制忽略的配置
├── babel.config.js: babel 的配置文件
├── package.json: 应用包配置文件
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件
(四)main.js和以前的不同之处
1、引入Vue
import Vue from 'vue'
//vue.js是完整版的Vue,包含:核心功能+模板解析器。
//vue.runtime.xxx.js是运行版的Vue,只包含:核心功能,没有模板解析器。
//因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体内容。
2、render函数
//render函数完成了这个功能:将App组件放入容器中,替代了之前的components
new Vue({
el:'#app',
//render函数完成了这个功能:将App组件放入容器中
render: h => h(App),
// components:{App},
})
二、ref属性
在节点上可以设置ref属性,这样就可以获取dom节点
<button ref="btn" @click="showDOM">点我输出上方的DOM元素</button>
通过this.$refs调用
console.log(this.$refs.btn) //真实DOM元素
三、props配置
(一)作用
用来父组件给子组件传值
(二)用法
//在父元素上传入值,key=value
<Student name="李四" sex="女" :age="18"/>
//在子元素接收
//简单声明接收
props:['name','age','sex']
//接收的同时对数据进行类型限制
props:{
name:String,
age:Number,
sex:String
}
//接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
props:{
name:{
type:String, //name的类型是字符串
required:true, //name是必要的
},
age:{
type:Number,
default:99 //默认值
},
sex:{
type:String,
required:true
}
}
//使用
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<h2>学生年龄:{{myAge+1}}</h2>
四、混合
(一)定义一个混合
创建一个mixin.js文件
export const hunhe = {
methods: {
showName(){
alert(this.name)
}
},
mounted() {
console.log('你好啊!')
},
}
export const hunhe2 = {
data() {
return {
x:100,
y:200
}
},
}
//向外暴露两个对象
(二)局部引用
引入一个hunhe
import {hunhe,hunhe2} from '../mixin'
export default {
name:'School',
data() {
return {
}
},
mixins:[hunhe,hunhe2],
}
(三)全局引用
在main.js中引入
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入混合
import {hunhe,hunhe2} from './mixin'
//关闭Vue的生产提示
Vue.config.productionTip = false
//注册混合
Vue.mixin(hunhe)
Vue.mixin(hunhe2)
//创建vm
new Vue({
el:'#app',
render: h => h(App)
})
五、插件
- Vue 插件是一个包含 install 方法的对象
- 通过 install 方法给 Vue 或 Vue 实例添加方法, 定义全局指令
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入插件
import plugins from './plugins'
//关闭Vue的生产提示
Vue.config.productionTip = false
//应用(使用)插件
Vue.use(plugins,1,2,3)
//创建vm
new Vue({
el:'#app',
render: h => h(App)
})
//设置一个插件,实现的一些方法
export default {
install(Vue,x,y,z){
console.log(x,y,z)
//全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
//定义全局指令
Vue.directive('fbind',{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
})
//定义混入
Vue.mixin({
data() {
return {
x:100,
y:200
}
},
})
//给Vue原型上添加一个方法(vm和vc就都能用了)
Vue.prototype.hello = ()=>{alert('你好啊')}
}
}
六、scoped
scoped专门加在组建的css样式上,用来防止脚手架整合时反生css样式冲突问题
<style scoped>
.demo{
background-color: skyblue;
}
</style>
同时,也可以指定语言
<style lang="less(css)" scoped>
.demo{
background-color: pink;
.atguigu{
font-size: 40px;
}
}
</style>
七、本地存储
(一)localStorage
localStorage指在计算机本地存储,即使浏览器关闭了,数据依旧保存
//添加 key-value
localStorage.setItem('msg','hello!!!')
//读取
localStorage.getItem('msg')
//删除
localStorage.removeItem('msg2')
//清除全部
localStorage.clear()
(二)sessionStorage
sessionStorage指在浏览器存储,浏览器关闭了,数据丢失
//添加 key-value
sessionStorage.setItem('msg','hello!!!')
//读取
sessionStorage.getItem('msg')
//删除
sessionStorage.removeItem('msg2')
//清除全部
sessionStorage.clear()
八、自定义事件
需求:父组件给子组件传值
(一)props实现
//父组件使用子组件时传入父组件方法
<School :getSchoolName="getSchoolName"/>
getSchoolName(name){
console.log('App收到了学校名:',name)
}
//子组件接收并使用
props:['getSchoolName']
sendSchoolName(){
this.getSchoolName(this.name)
}
//实现父传子
(二)子给父传递数据(使用@或v-on)
//父组件设置绑定事件,
<Student @zichao="getStudentName"/>
getStudentName(name,...params){
console.log('App收到了学生名:',name,params)
}
//子组件
sendStudentlName(){
//触发Student组件实例身上的zichao事件.并传值
this.$emit('zichao',this.name,666,888,900)
// this.$emit('demo')
// this.$emit('click')
},
(三)给父传递数据(使用ref)
//父组件设置ref,并绑定事件
<Student ref="student" />
mounted() {
this.$refs.student.$on('zichao',this.getStudentName)
//绑定自定义事件
this.$refs.student.$once('zichao',this.getStudentName)
//绑定自定义事件(一次性)
},
//子组件触发一致
九、全局事件总线
全局事件总线可以实现各个组件间传值
(一)创建事件总线
//main.js创建vm时
new Vue({
el:'#app',
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线
},
})
(二)接收数据
使用$on方法
mounted() {
this.$bus.$on('hello',(data)=>{
console.log('我是School组件,收到了数据',data)
})
}
(三)发送数据
使用$emit方法
methods: {
sendStudentName(){
this.$bus.$emit('hello',this.name)
}
}
(四)解绑事件
使用$off方法
beforeDestroy() {
this.$bus.$off('hello')
}
十、$nextTick
$nextTick是一个生命周期函数,当页面已经渲染过后将会调用该方法里的回调函数
什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行
//和之前的生命函数不同,他可以写在方法内
this.$nextTick(function(){
//执行方法
})
十一、过度和动画
(一)原理
- 操作 css 的 trasition 或 animation
- vue 会给目标元素添加/移除特定的 clas
//定义一个动画
@keyframes zichao {
from{
transform: translateX(-100%);
}
to{
transform: translateX(0px);
}
}
(二)过渡的相关类名
- xxx-enter-active: 指定显示的 transition
- xxx-leave-active: 指定隐藏的 transition
- xxx-enter/xxx-leave-to: 指定隐藏时的样式
//必须在实现动画的元素外包裹transition,并指定name
<transition name="hello" appear>
<h1 v-show="isShow">你好啊!</h1>
</transition>
//使用
.hello-enter-active{
animation: zichao 0.5s linear;
}
.hello-leave-active{
animation: zichao 0.5s linear reverse;
}
//其他类名
/* 进入的起点、离开的终点 */
.hello-enter,.hello-leave-to{
transform: translateX(-100%);
}
.hello-enter-active,.hello-leave-active{
transition: 0.5s linear;
}
/* 进入的终点、离开的起点 */
.hello-enter-to,.hello-leave{
transform: translateX(0);
}
(三)引入外部动画
https://animate.style/
//引入
import 'animate.css'
//使用
<transition-group
appear
name="animate__animated animate__bounce"
enter-active-class="animate__swing"
leave-active-class="animate__backOutUp"
>
<h1 v-show="!isShow" key="1">你好啊!</h1>
</transition-group>
需要用transition-group包裹需要动画元素,并设置开始和结束动画
十二、插槽
(一)默认插槽
使用slot
//在子组件使用slot定义一个插槽(挖个坑,等着组件的使用者进行填充)
<slot>我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>
//在父组件中使用双标签,中间添加想在插槽中设置的元素,元素将会发在子组件设置插槽的位置
<Category title="美食" >
<img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
</Category>
(二)具名插槽
使用slot时使用name属性取名
//子组件定义一个插槽(挖个坑,等着组件的使用者进行填充)
<slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现1</slot>
<slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现2</slot>
//父组件,使用slot根据名字插入
<img slot="center" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
<a slot="footer">更多美食</a>
(三)作用域插槽
数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。
//父组件
<Category>
<template scope="scopeData">
<!-- 生成的是ul列表 -->
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
//子组件
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:'Category',
props:['title'],
//数据在子组件自身
data() {
return {
games:['红色警戒','穿越火线','劲舞团','超级玛丽']
}
},
}
</script>
十三、Vuex
(一)概念
在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
(二)搭建vuex环境
1、创建文件:
src/store/index.js
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions对象——响应组件中用户的动作
const actions = {}
//准备mutations对象——修改state中的数据
const mutations = {}
//准备state对象——保存具体的数据
const state = {}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
2、引入
在main.js
中创建vm时传入store
配置项
//引入store
import store from './store'
......
//创建vm
new Vue({
el:'#app',
render: h => h(App),
store
})
(三)基本使用
1、 初始化数据
配置actions
、配置mutations
,操作文件store.js
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)
const actions = {
//响应组件中加的动作
jia(context,value){
context.commit('JIA',value)
},
}
const mutations = {
//执行加
JIA(state,value){
state.sum += value
}
}
//初始化数据
const state = {
sum:0
}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
2、组件中读取vuex中的数据
$store.state.sum
<h1>当前求和为:{{$store.state.sum}}</h1>
3. 组件中修改vuex中的数据
若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch
,直接编写commit
$store.dispatch('action中的方法名',数据)
incrementOdd(){
this.$store.dispatch('jia',this.n)
}
$store.commit('mutations中的方法名',数据)
increment(){
this.$store.commit('JIA',this.n)
}
(四)getters的使用
1、概念
当state中的数据需要经过加工后再使用时,可以使用getters加工。
2、配置
在store.js
中追加getters
配置
const getters = {
bigSum(state){
return state.sum * 10
}
}
//创建并暴露store
export default new Vuex.Store({
......
getters
})
3、读取
组件中读取数据:$store.getters.bigSum
<h3>当前求和放大10倍为:{{$store.getters.bigSum}}</h3>
(五)简洁获取state数据
1、mapState方法
用于帮助我们映射state
中的数据为计算属性
computed: {
//借助mapState生成计算属性:sum、school、subject(对象写法)
...mapState({sum:'sum',school:'school',subject:'subject'}),
//借助mapState生成计算属性:sum、school、subject(数组写法)
...mapState(['sum','school','subject']),
}
2、mapGetters方法
用于帮助我们映射getters
中的数据为计算属性
computed: {
//借助mapGetters生成计算属性:bigSum(对象写法)
...mapGetters({bigSum:'bigSum'}),
//借助mapGetters生成计算属性:bigSum(数组写法)
...mapGetters(['bigSum'])
}
(六)简洁设置方法
1、mapActions
用于帮助我们生成与actions
对话的方法,即:包含$store.dispatch(xxx)
的函数
methods:{
//靠mapActions生成:incrementOdd、incrementWait(对象形式)
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
//靠mapActions生成:incrementOdd、incrementWait(数组形式)
...mapActions(['jiaOdd','jiaWait'])
}
2、mapMutations方法
用于帮助我们生成与mutations
对话的方法,即:包含$store.commit(xxx)
的函数
methods:{
//靠mapActions生成:increment、decrement(对象形式)
...mapMutations({increment:'JIA',decrement:'JIAN'}),
//靠mapMutations生成:JIA、JIAN(对象形式)
...mapMutations(['JIA','JIAN']),
}
(七)模块化+命名空间
1、修改store.js
//向外暴露两个Vuex实例
const countAbout = {
namespaced:true,//开启命名空间
state:{x:1},
mutations: { ... },
actions: { ... },
getters: {
bigSum(state){
return state.sum * 10
}
}
}
const personAbout = {
namespaced:true,//开启命名空间
state:{ ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
countAbout,
personAbout
}
})
//也可以设置多个文件,统一的在index里做引入
2、开启命名空间后,组件中读取state数据
//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),
3、开启命名空间后,组件中读取getters数据
//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])
4、开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
5、开启命名空间后,组件中调用commit
//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
十四、路由
(一)理解
理解: 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。
前端路由:key是路径,value是组件。
(二)基本使用
1、安装vue-router
命令:npm i vue-router
注意版本
2. 应用插件:
Vue.use(VueRouter)
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入VueRouter
import VueRouter from 'vue-router'
//引入路由器
import router from './router'
//关闭Vue的生产提示
Vue.config.productionTip = false
//应用插件
Vue.use(VueRouter)
//创建vm
new Vue({
el:'#app',
render: h => h(App),
router:router
})
3、编写router配置项
src创建router文件夹编写index.js文件
//引入VueRouter
import VueRouter from 'vue-router'
//引入Luyou 组件
import About from '../components/About'
import Home from '../components/Home'
//创建router实例对象,去管理一组一组的路由规则
const router = new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
//暴露router
export default router
4、实现切换和指定展示位置
//router-link其实就是a标签,to属性就是要展示的组件的path
<router-link active-class="active" to="/about">About</router-link>
//指定展示位置
<router-view></router-view>
5、注意
- 路由组件通常存放在
pages
文件夹,一般组件通常存放在components
文件夹。 - 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。
- 每个组件都有自己的
$route
属性,里面存储着自己的路由信息。 - 整个应用只有一个router,可以通过组件的
$router
属性获取到。
(三)多级路由
1、配置路由规则
使用children配置项
routes:[
{
path:'/about',
component:About,
},
{
path:'/home',
component:Home,
children:[ //通过children配置子级路由
{
path:'news', //此处一定不要写:/news
component:News
},
{
path:'message',//此处一定不要写:/message
component:Message
}
]
}
]
2、跳转
<router-link to="/home/news">News</router-link>
(四)路由的query参数
1、传递参数
<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳转</router-link>
<!-- 跳转并携带query参数,to的对象写法 -->
<router-link
:to="{
path:'/home/message/detail',
query:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
2、接收参数
//$route.query.id
//$route.query.title
<li>消息编号:{{$route.query.id}}</li>
<li>消息标题:{{$route.query.title}}</li>
(五)命名路由
1、 作用
可以简化路由的跳转。
2、 使用
{
path:'/demo',
component:Demo,
children:[
{
path:'test',
component:Test,
children:
[
{
name:'hello' //给路由命名
path:'welcome',
component:Hello,
}
]
}
]
}
3、简化跳转
<!--简化前,需要写完整的路径 -->
<router-link to="/demo/test/welcome">跳转</router-link>
<!--简化后,直接通过名字跳转 -->
<router-link :to="{name:'hello'}">跳转</router-link>
<!--简化写法配合传递参数 -->
<router-link
:to="{
name:'hello',
query:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
(六)路由的params参数
1、 配置路由
声明接收params参数
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News
},
{
component:Message,
children:[
{
name:'xiangqing',
path:'detail/:id/:title', //使用占位符声明接收params参数
component:Detail
}
]
}
]
}
2、传递参数
<!-- 跳转并携带params参数,to的字符串写法 -->
//666,你好将作为参数发过去
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link
:to="{
name:'xiangqing',//特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!
params:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
3、接收参数:
$route.params.id
$route.params.title
<li>消息编号:{{$route.params.id}}</li>
<li>消息标题:{{$route.params.title}}</li>
(七)路由的props配置
作用:让路由组件更方便的收到参数
{
name:'xiangqing',
path:'detail/:id',
component:Detail,
//第一种写法:props值为对象,该对象中所有的key-value的组合最终都会通过props传给Detail组件
props:{a:900}
//第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
props:true
//第三种写法:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
props(route){
return {
id:route.query.id,
title:route.query.title
}
}
}
//Detail组件
<li>消息编号:{{id}}</li>
<li>消息标题:{{title}}</li>
(八)<router-link>
的replace属性
- 作用:控制路由跳转时操作浏览器历史记录的模式
- 浏览器的历史记录有两种写入方式:分别为
push
和replace
,push
是追加历史记录,replace
是替换当前记录。路由跳转时候默认为push
- 如何开启
replace
模式:<router-link replace .......>News</router-link>
//代码控制
this.$router.forward() //前进到
this.$router.back() //后退
this.$router.go() //可前进也可后退
(九)编程式路由导航
1、作用
不借助<router-link>
实现路由跳转,让路由跳转更加灵活
2、具体编码
//$router的两个API
this.$router.push({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.replace({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.push()//通过push方式跳转到指定name的组件
this.$router.replace()//通过replace方式跳转到指定name的组件
(十)缓存路由组件
1、 作用
让不展示的路由组件保持挂载,不被销毁。
2、具体编码:
//添加include属性
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
<!-- 缓存多个路由组件 -->
<keep-alive :include="['News','Message']">
<router-view></router-view>
</keep-alive>
(十一)两个新的生命周期钩子
1、 activated
路由组件被激活时触发。
activated() {
console.log('News组件被激活了')
}
2、deactivated
路由组件失活时触发。
deactivated() {
console.log('News组件失活了')
}
(十二)路由守卫
1、 作用:对路由进行权限控制
2、分类:全局守卫、独享守卫、组件内守卫
3、全局守卫:
//创建并暴露一个路由器
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{title:'关于'}
},
{
name:'zhuye',
path:'/home',
component:Home,
meta:{title:'主页'},
children:[
{
name:'xinwen',
path:'news',
component:News,
meta:{isAuth:true,title:'新闻'}
},
{
name:'xiaoxi',
path:'message',
component:Message,
meta:{isAuth:true,title:'消息'},
children:[
{
name:'xiangqing',
path:'detail',
component:Detail,
meta:{isAuth:true,title:'详情'},
props($route){
return {
id:$route.query.id,
title:$route.query.title,
a:1,
b:'hello'
}
}
}
]
}
]
}
]
})
//全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{
if(to.meta.isAuth){ //判断是否需要鉴权
if(localStorage.getItem('school')==='zichao'){
next()
}else{
alert('无权限查看')
}
}else{
next()
}
})
//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
document.title = to.meta.title || 'zichao'
})
export default router
4、独享守卫
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{title:'关于'}
},
{
name:'zhuye',
path:'/home',
component:Home,
meta:{title:'主页'},
children:[
{
name:'xinwen',
path:'news',
component:News,
meta:{isAuth:true,title:'新闻'},
//组件内
beforeEnter: (to, from, next) => {
if(to.meta.isAuth){ //判断是否需要鉴权
if(localStorage.getItem('school')==='atguigu'){
next()
}else{
alert('学校名不对,无权限查看!')
}
}else{
next()
}
}
}
5、组件内
//每个组件
<script>
export default {
name:'About',
//通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {
console.log('About--beforeRouteEnter',to,from)
if(to.meta.isAuth){ //判断是否需要鉴权
if(localStorage.getItem('school')==='atguigu'){
next()
}else{
alert('学校名不对,无权限查看!')
}
}else{
next()
}
},
//通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {
console.log('About--beforeRouteLeave',to,from)
next()
}
}
</script>
(十三)路由器的两种工作模式
- 对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。
- hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
- hash模式:
①地址中永远带着#号,不美观 。
② 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
③兼容性较好。 - history模式:
①地址干净,美观 。
②兼容性和hash模式相比略差。
③应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。
//设置路由为history模式
const router = new VueRouter({
mode:'history',