文章目录
1.1 模板语法
Vue模板语法包括两大类
1.插值语法
写法:{{xxx}},xxx是js表达式,可以直接读取data内容
2.指令语法
v-bind指令
单向绑定,数据只能从data流向页面
写法:
<a v-bind:href=""></a>
<a :href=""></a>
v-model指令
双向数据绑定,数据不仅能从data流向页面,还能从页面流向data
写法:
<input type="text" v-model="name"></input>
v-for指令
用于展示列表数据
注意:key可以是index,更好的是遍历对象的唯一标识
写法:
<li v-for="(item, index) in items" :key="index">
{{key}}:{{value}}
</li>
v-on指令
绑定事件监听
写法:
<button @click="xxx">点我</button>
<button v-on:click="xxx($event)">点我</button> //可以传参
用法:
1.事件的回调需要配置在methods对象中,最终会在vm
2.methods中配置的函数,不能使用箭头函数,否则this就不是vm了
3.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或者组件实列对象
Vue中的事件修饰符
prevent | 阻止默认事件 |
---|---|
stop | 阻止事件冒泡 |
once | 事件只能触发一次 |
capture | 使用事件的捕获模式 |
self | 只有event.target是当前操作的元素时才触发事件 |
passive | 事件的默认行为立即执行,无需等待事件回调执行完毕 |
键盘事件
Vue常用的按键别名
按键 | 别名 | 代码中 |
---|---|---|
回车 | enter | @keyup.enter=“xxx” |
删除 | delete | @keyup.delete=“xxx” |
退出 | esc | @keyup.esc=“xxx” |
空格 | space | @keyup.space=“xxx” |
换行 | tab | @keydown.tab=“xxx” |
上 | up | @keyup.up=“xxx” |
下 | down | @keyup.down=“xxx” |
左 | left | @keyup.left=“xxx” |
右 | right | @keyup.right=“xxx” |
v-if v-else-if v-else指令
条件渲染
写法:
<div v-if="表达式"></div>
<div v-else-if="表达式"></div>
<div v-else="表达式"></div>
用法:
切换频率较低的场景,因为不展示的DOM元素直接被移除
v-show指令
写法:
<div v-show="表达式"></div>
用法:
切换频率较高的场景,不展示的DOM未被移除,仅仅是使用样式隐藏display:none
v-text指令
向其所在的节点中渲染文本内容
写法:
<div v-text="name"></div>
与插值语法的区别:
v-text会替换掉节点中的内容,{{xxx}}则不会,更灵活
v-html指令
向指定节点中渲染包含html结构的内容
写法:
<div v-html="name"></div>
name:'<h3>你好啊</h3>'
呈现:h3标签的你好啊
v-cloak指令
本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
使用css配合v-cloak可以解决网速慢时展示出{{xxx}}的问题
写法:
<h2 v-cloak>{{xxx}}</h2>
v-once指令
所在节点初次动态渲染后,就视为静态内容了
以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
写法:
<h2 v-once>{{xxx}}</h2> //数据改变不会改变其值
v-pre指令
跳过v-pre所在节点的编译过程
可利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译
写法:
<h2 v-pre>Vue</h2>
1.2 计算属性
语法:
computed:{
}
定义:
要用的属性不存在,需要通过已有属性计算得来
原理:
底层借助了Object.defineproperty()方法提供的getter和setter
备注:
1.计算属性最终会出现在vm上,直接读取使用即可
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
3.如果计算属性不考虑修改,可以使用计算属性的简写形式
写法:
<script>
var vue = new Vue({
el : '#root',
data : {
firstName:'张',
lastName:'三'
},
methods : {
},
computed:{
//完整写法
// fullName:{
// get(){
// console.log('get被调用了')
// return this.firstName+'-'+this.lastName
// },
// set(value){
// var arr = value.split('-');
// this.firstName=arr[0];
// this.lastName=arr[1]
// }
// }
//简写
fullName(){
return this.firstName+'-'+this.lastName
}
}
});
</script>
1.3 侦听属性
语法:
//第一种
watch:{
}
//第二种
vm.$watch()
定义:
当被监听的属性变化时,回调函数自动调用,进行相关操作
配置项属性:
immediate:false //改为true,则初始化调用一次
deep:true //可以监听对象内部值的改变
注意:
1.监听的属性必须存在,才能进行监视,既可以监视data,也可以监视计算属性
2.使用watch时根据监视数据的具体结构,决定是否采用深度监视
计算属性VS侦听属性
区别:
1.computed能完成的功能,watch都可以完成
2.watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作
两个重要的小原则:
1.所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象
1.4 过滤器
定义:
要对显示的数据进行特定格式化后在显示
用法:
//注册
Vue.filter(name,callback) //全局过滤器
new Vue ({//局部过滤器
filters:{
过滤器名称(val,规则){}
}
})
//实现
{{数据 | 过滤器名称 | 过滤器名称}}
1.5 Vue生命周期
生命周期
1.又名生命周期回调函数、生命周期函数、生命周期钩子
2.是什么?Vue在关键时刻帮我们调用的一些特殊名称的函数
3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
4.生命周期函数中的this指向是vm或组件实例对象
原理图:
写法:
<script>
var vm = new Vue({
el : '#root',
data : { },
methods : { } ,
beforeCreate() {
},
created() {
},
beforeMount() {
},
mounted() {
//常用来发送ajax请求、启动定时器,绑定自定义事件、订阅消息等初始化操作
},
beforeUpdate() {
},
updated() {
},
beforeDestroy() {
//清除定时器、解绑自定义事件、取消订阅消息等收尾工作
},
destroyed() {
},
});
</script>
2.1 组件化编程
1. 定义组件
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的options几乎一样,但也有点区别:
a.el不要写,因为最终所有的组件都要经过一个vm的管理,由vm中的el才决定服务哪个容器
b.data必须写成函数,避免组件被复用时,数据存在引用关系
写法:
const school = Vue.extend({
template: `
`,
data() {
return {
}
},
methods: {
}
})
2. 注册组件
局部注册:
var vm = new Vue({
el: '#root',
components: {
}
});
全局注册:
Vue.component('组件名',组件)
3. 使用组件
编写组件标签如:<School></School>
组件注意事项
一个单词组成
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)
组件标签
第一种写法:
第二种写法:(需要Vue脚手架支持)
4. VueComponent
组件实例对象vc
重要的内置关系:
VueComponent.prototype._proto_ === Vue.prototype
3.1 Vue CLI
1. 具体步骤
全局安装 @Vue/cli npm install -g @vue/cli
切换到创建项目的目录,使用命令创建项目 vue create xxx
选择使用vue的版本
启动项目 npm run serve
打包项目 npm run build
2.脚手架文件结构
.文件目录
├── 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: 包版本控制文件
3.render函数
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
el:'#app',
// render函数功能:将App组件放入容器中
// 简写形式
render: h => h(App),
// 完整形式
// render(createElement){
// return createElement(App)
// }
})
4.ref属性
ref被用来给元素或子组件注册引用信息(id的替代者)
使用方式:
<h1 v-text="msg" ref="title"></h1> //html标签上,获取的是DOM元素
<School ref="sch"/> //组件标签上,获取的是组件实例对象vc
//获取
this.$refs.xxx
5.props配置项
props让组件接收外部传过来的数据
适用于:
父组件 ==> 子组件 通信
子组件 ==> 父组件 通信 (要求父组件先给子组件一个函数)
传递数据:
<Student name="李四" sex="男" :age="18"></Student>
接收数据:
//简单接收
props:['name','sex','age']
//接收数据的同时并且对类型进行限制
// props:{
// name:String,
// sex:String,
// age:Number
// }
//接收数据的同时对类型进行限制并设置默认值
/* props:{
name:{
type:String,
required:true,
},
sex:{
type:String,
required:false,
default:'男'
},
age:{
type:Number,
required:false,
default:99
}
} */
备注:props是只读的,若需要修改,复制props内容到data中,然后修改data中的数据
6.mixin混入
可以把多个组件共用的配置提取成一个混入对象
定义混入:
export const mixin = {
methods: {
showName() {
alert(this.name)
}
},
}
使用混入:
//全局混入
Vue.mixin(混入名)
//局部混入
mixins:[‘xxx]
注意事项:
a.组件和混入对象含有同名选项时,这些选项将以恰当的方式进行"合并",在发生冲突时以组件优先
b.同名生命周期钩子将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用
7.plugin插件
用于增强Vue
本质:包含install方法的一个对象,install第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
定义插件:
export default {
install(Vue){
Vue.filter('mySlice',function(params) {
return params.slice(0,4)
})
}
}
使用插件:
Vue.use(插件)
8.Scoped
作用:
让样式在局部生效,防止冲突
写法:
<style scoped>
9.本地存储
游览器通过Window.sessionStorage 和Window.localStorage属性来实现本地存储机制
相关API:
方法 | 含义 |
---|---|
xxxStorage.setItem(‘key’,‘value’) | 该方法接受一个键和值作为参数,会把键值添加到存储中,如果键名存在,则更新对应的值 |
xxxStorage.getItem(‘key’) | 该方法接收一个键名作为参数,返回键名对应的值 |
xxxStorage.removeItem(‘key’) | 该方法接收一个键名作为参数,并把该键名从存储中删除 |
xxxStorage.clear() | 该方法会清空存储中的所有数据 |
注意事项:
SessionStorage存储的内容会随着游览器窗口关闭而消失
LocalStorage存储的内容,需要手动清楚才会消失
xxxStorage.getItem(‘key’)如果key对应的value获取不到,返回值则为null
10.组件的自定义事件
组件间通信的方式,适用于:子组件 ===> 父组件
1.绑定自定义事件
子组件想给父组件传数据,需要在父组件中给子组件绑定一个自定义事件(事件的回调在父组件中)
第一种方式:
<School @事件名="方法"></School>
<School v-on:事件名="方法"></School>
第二种方式:
<子组件标签 ref="xxx"></子组件标签>
mounted(){
//回调函数要么配置在methods中,要么用箭头函数,否则this指向会出问题
this.$refs.子组件.$on('事件名', 回调函数)
//this.$refs.子组件.$once('事件名', 回调函数) //事件触发一次
}
2.触发自定义事件
this.$emit('事件名', 数据)
3.解绑自定义事件
this.$off('事件名') //解绑一个自定义事件
this.$off(['事件名','事件名']) //解绑多个自定义事件
this.$off() //解绑所有的自定义事件
11.全局事件总线
一种可以在任意组件间通信的方式,本质上就是一个对象,它必须满足以下条件:
所有的组件对象都必须能看见他
这个对象必须能够使用**$on $emit $off** 方法去绑定、触发和解绑事件
1.定义全局事件总线
new Vue({
...
beforeCreate() {
Vue.prototype.$bus = this // 安装全局事件总线,$bus 就是当前应用的 vm
},
...
})
2.使用全局事件总线
接收数据方:
组件想接收数据,则在该组件中给$bus绑定自定义事件,事件的回调留在该组件自身
export default {
methods(){
demo(data){...}
}
...
mounted() {
//第一种 配合methods使用
this.$bus.$on('xxx',this.demo)
//第二种 使用箭头函数
this.$bus.$on('xxx', (data) => {
...
})
}
}
提供数据方:
this.$bus.$emit('xxx',提供给的数据)
3.解绑事件
在beforeDestroy钩子中,用$off()去解绑当前组件所用到的事件
beforeDestroy() {
this.$bus.$off('事件名')
},
12.消息的订阅与发布
消息订阅与发布也是一种组件间通信的方式,适用于任意组件间通信
使用步骤:
1.安装pubsub
npm i pubsub-js
2.引入pubsub
import pubsub from 'pubsub-js'
3.使用pubsub:
接收数据方(订阅):
哪个组件想接收数据,则在该组件订阅消息,订阅的回调在自身
export default {
methods: {
demo(msgName, data) {...}
}
...
mounted() {
this.pid = pubsub.subscribe('xxx',this.demo)
}
}
发送数据方(发布):
pubsub.publish('xxx',data)
取消订阅:
beforeDestroy() {
pubsub.unsubscribe(pid) //pid为订阅方返回的id值
},
13.$nextTick
这是一个生命周期钩子
this.$nextTick(回调函数)在下一次DOM更新结束后指向其指定的回调
什么时候用?当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行
14.过度与动画
Vue封装的过度与动画:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名
1.样式
元素进入的样式 | 元素离开的样式 | ||
---|---|---|---|
进入的起点 | v-enter | 离开的起点 | v-leave |
进入的过程中 | v-enter-active | 离开的过程中 | v-leave-active |
进入的终点 | v-enter-to | 离开的终点 | v-leave-to |
2.使用
使用包裹要过度的元素,并配置name属性,此时需要将上面的v换成name,如果需要让页面一开始就显示动画,需要加appear
15.Ajax
1.axios
安装:
npm install axios
配置:
vue.config.js添加配置
module.exports = {
devServer: {
proxy: {
'/api1': { // 匹配所有以 '/api1'开头的请求路径
target: 'http://localhost:5000', // 代理目标的基础路径
pathRewrite: {'^/api1':''}, // 代理往后端服务器的请求去掉 /api1 前缀
ws: true, // WebSocket
changeOrigin: true,
},
'/api2': {
target: 'http://localhost:5001',
pathRewrite: {'^/api2': ''},
changeOrigin: true
}
}
}
}
/*
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
changeOrigin默认值为true
*/
用法:
axios.get(`https://api.github.com/search/users?q=${this.keyWorld}`).then(
response => {
console.log('请求成功了', response.data)
this.$bus.$emit('updateListData', { isLoading: false, errMsg: '', users: response.data.items })
},
error => {
console.log('请求失败了')
this.$bus.$emit('updateListData', { isLoading: false, errMsg: error.message, users: [] })
}
)
2.vue-resource
安装:
npm i vue-resource
用法:
this.$http.get(`https://api.github.com/search/users?q=${this.keyWorld}`).then(
response => {
console.log('请求成功了', response.data)
this.$bus.$emit('updateListData', { isLoading: false, errMsg: '', users: response.data.items })
},
error => {
console.log('请求失败了')
this.$bus.$emit('updateListData', { isLoading: false, errMsg: error.message, users: [] })
}
)
16.slot插槽
插槽:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式。
适用于:父组件 ===> 子组件
1.默认插槽
父组件中:
<Category>
<div>html结构1</div>
</Category>
子组件中:Category
<template>
<div>
<!-- 定义插槽 -->
<slot>插槽默认内容...</slot>
</div>
</template>
2.具名插槽
父组件指明放入子组件的哪个插槽
父组件中:
<Category>
<template slot="center">
<div>html结构1</div>
</template>
<template v-slot:footer>
<div>html结构2</div>
</template>
</Category>
子组件中:
<template>
<div>
<!-- 定义插槽 -->
<slot name="center">插槽默认内容...</slot>
<slot name="footer">插槽默认内容...</slot>
</div>
</template>
3.作用域插槽
scope用于父组件接收子组件在插槽放入的数据
父组件中:
<Category>
<template scope="scopeData">
<!-- 生成的是ul列表 -->
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
<Category>
<template slot-scope="scopeData">
<!-- 生成的是h4标题 -->
<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
</template>
</Category>
子组件中:
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:'Category',
props:['title'],
//数据在子组件自身
data() {
return {
games:['红色警戒','穿越火线','劲舞团','超级玛丽']
}
},
}
</script>
3.1 Vuex
1.Vuex是什么
专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
2.什么时候使用Vuex
多个组件依赖于同一状态
来自不同组件的行为需要变更同一状态
3.Vuex原理图
4.搭建Vuex环境
安装:
npm i vuex
配置:
src/store/index.js,该文件创建Vuex最为核心的store
import Vue from 'vue'
import Vuex from 'vuex' // 引入Vuex
Vue.use(Vuex) // 应用Vuex插件
const actions = {} // 准备actions——用于响应组件中的动作
const mutations = {} // 准备mutations——用于操作数据(state)
const state = {} // 准备state——用于存储数据
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
src/main.js中创建vm时传入store配置项
import Vue from 'vue'
import App from './App.vue'
import store from './store' // 引入store
Vue.config.productionTip = false
new Vue({
el: '#app',
render: h => h(App),
store, // 配置项添加store
beforeCreate() {
Vue.prototype.$bus = this
}
})
使用:
组件中修改vuex中的数据:
$store.dispatch('action中的方法名',数据)
$store.commit('mutations中的方法名',数据)
若没有网络请求或其他业务逻辑,组件可越过actions,即不写dispatch,直接写commit
组件中读取vuex中的数据:
$store.state.数据
5.getter配置项
概念:
当state中的数据需要经过加工后在使用时,可以使用getters加工,相当于全局计算属性
使用:
......
const getters = {
bigSum(state){
return state.sum * 10
}
}
// 创建并暴露store
export default new Vuex.Store({
......
getters
})
组件中读取数据:
$store.getters.方法名
6.4个map方法的使用
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'])
},
3.mapActions
用于帮助生成与actions对话的方法,即包含$store.dispatch(xxx)的函数
methods:{
//靠mapActions生成:incrementOdd、incrementWait(对象形式)
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
//靠mapActions生成:incrementOdd、incrementWait(数组形式)
...mapActions(['jiaOdd','jiaWait'])
}
4.mapMutations
用于帮助生成与mutations对话的方法,即包含$store.commit(xxx)的函数
methods:{
//靠mapActions生成:increment、decrement(对象形式)
...mapMutations({increment:'JIA',decrement:'JIAN'}),
//靠mapMutations生成:JIA、JIAN(对象形式)
...mapMutations(['JIA','JIAN']),
}
注意:mapActions与mapMutations使用时,若需要传递参数,需要**在模板中绑定事件时传递好参数**,否则参数是事件对象
5.模块化+命名空间
目的:
让代码更好维护,让多种数据分类更加明确
修改store.js
为了解决不同模块命名冲突的问题,将不同模块添加namespaced:true,之后在不同页面中引入actions、mutations、getter时,需要加上所属的模块名
开启命名空间后,组件读取state的数据:
// 方式一:自己直接读取
this.$store.state.personAbout.list
// 方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),
开启命名空间后,组件读取getters的数据:
//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])
开启命名空间后,组件中调用dispatch:
//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
开启命名空间后,组件中调用mutations:
//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
4.1 Vue Router
1.vue-router
Vue的一个插件库,专门用来实现SPA应用
2.SPA
单页Web的应用(single page web application, SPA)
整个应用只有一个完整的页面
点击页面中的导航链接不会刷新页面,只会做页面的局部刷新
数据需要通过ajax请求获取
3.路由
什么是路由?
一个路由就是一组映射关系(key-value)
key为路径,value可能是function或component
路由的分类
后端路由
理解:value是function,用于处理客户端提交的请求
工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回响应数据
前端路由
理解:value是component,用于展示页面内容
工作过程:当游览器的路径改变时,对应的组件就会显示
4.使用
安装:
npm i vue-router
应用插件:
Vue.use(VueRouter)
基本路由:
import VueRouter from 'vue-router' // 引入VueRouter
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
实现切换:
/**
<router-link></router-link> 游览器会被替换为a标签
active-class可配置高亮样式
*/
<router-link active-class="active" to="/about">About</router-link>
展示位:
<router-view></router-view>
注意事项:
1.路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹
2.通过切换,隐藏了的路由组件,默认是被销魂掉的,需要的时候再去挂载
3.每个组件都有自己的**$route**属性,里面存储着自己的路由信息
4.整个应用只有一个** r o u t e r ∗ ∗ , 可 以 通 过 组 件 的 router**,可以通过组件的 router∗∗,可以通过组件的router属性获取到
多级路由:
routes:[
{
path:'/about',
component:About,
},
{
path:'/home',
component:Home,
children:[ // 通过children配置子级路由
{
path:'news', // 此处一定不要带斜杠,写成 /news
component:News
},
{
path:'message', // 此处一定不要写成 /message
component:Message
}
]
}
]
跳转(写完整路径):
<router-link to="/home/news">News</router-link>
5.query
路由的query参数
传递参数:
<!-- 跳转并携带query参数,to的字符串写法 -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">跳转</router-link>
<!-- 跳转并携带query参数,to的对象写法(推荐) -->
<router-link
:to="{
path:'/home/message/detail',
query:{
id: m.id,
title: m.title
}
}"
>跳转</router-link>
接收参数:
$route.query.id
$route.query.title
6.命名路由
作用:
可以简化路由的跳转
使用:
a.给路由命名
{
path:'/demo',
component:Demo,
children:[
{
path:'test',
component:Test,
children:[
{
name:'hello' // 给路由命名
path:'welcome',
component:Hello,
}
]
}
]
}
b.简化跳转
<!--简化前,需要写完整的路径 -->
<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>
7.params
使用params参数时,需要配置路由,使用占位符声明接收params参数
配置:
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News
},
{
component:Message,
children:[
{
name:'xiangqing',
path:'detail/:id/:title', //使用占位符声明接收params参数
component:Detail
}
]
}
]
}
传递参数:
特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置
<!-- 跳转并携带params参数,to的字符串写法 -->
<router-link :to="/home/message/detail/666/你好">跳转</router-link>
<!-- 跳转并携带params参数,to的对象写法 -->
<router-link
:to="{
name:'xiangqing',
params:{
id:666,
title:'你好'
}
}"
>跳转</router-link>
接收参数:
$route.params.id
$route.params.title
8.路由的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
}
}
}
案例:
路由配置:
import VueRouter from "vue-router";
import Home from '../pages/Home'
import About from '../pages/About'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'
export default new VueRouter({
routes:[
{
path: '/about',
component: About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News
},
{
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'detail/:id/:title',
component:Detail,
// props的第一种写法,值为对象,
// 该对象中的所有key-value都会以props的形式传给Detail组件
// props:{a:1,b:'hello'}
// props的第二种写法,值为布尔值,
// 若布尔值为真,会把该路由组件收到的所有params参数,以props的形式传给Detail组件
// props:true
// props的第三种写法,值为函数
props(params) { // 这里可以使用解构赋值
return {
id: params.id,
title: params.title,
}
}
}
]
}
]
}
]
})
传递参数:
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<router-link :to="{
name:'xiangqing',
params:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>
</li>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>
<script>
export default {
name:'News',
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
}
}
</script>
接收参数:
<template>
<ul>
<li>消息编号:{{ id }}</li>
<li>消息标题:{{ title }}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
props:['id','title']
}
</script>
9.replace
作用:
控制路由跳转时操作游览器历史记录的模式
游览器的历史记录的两种写入方式:
push:是追加历史记录,默认方式
replace:是替换当前记录
开启replace模式:
<router-link :replace="true" >News</router-link>
<router-link replace >News</router-link>
10.编程式路由导航
作用:
不借助router-link实现路由跳转,让路由跳转更加灵活
API:
写法 | |
---|---|
this.$router.push({}) | 内穿的对象与router-link中的to相同 |
this.$router.reolace({}) | |
this.$router.forward() | 前进 |
this.$router.back() | 后退 |
this.$router.go(n) | 可前进也可后退,n为正数前进n,负数为后退n |
示例:
this.$router.push({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.replace({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
<template>
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue Router Demo</h2>
<button @click="back">后退</button>
<button @click="forward">前进</button>
<button @click="test">测试一下go</button>
</div>
</div>
</template>
<script>
export default {
name:'Banner',
methods:{
back(){
this.$router.back()
},
forward(){
this.$router.forward()
},
test(){
this.$router.go(3)
}
},
}
</script>
11.缓存路由组件
作用:
让不展示的路由组件保持挂载,不被销魂
示例:
// 缓存一个路由组件
<keep-alive include="News"> // include中写想要缓存的组件名,不写表示全部缓存
<router-view></router-view>
</keep-alive>
// 缓存多个路由组件
<keep-alive :include="['News','Message']">
<router-view></router-view>
</keep-alive>
12.activated deactivated
概念:
activated和deactivated是路由组件所独有的两个钩子,用于捕获路由组件的激活状态
使用:
activated:路由组件被激活时触发
deactivated:路由组件失活时触发
示例:
<template>
<ul>
<li :style="{opacity}">欢迎学习vue</li>
<li>news001 <input type="text"></li>
<li>news002 <input type="text"></li>
<li>news003 <input type="text"></li>
</ul>
</template>
<script>
export default {
name:'News',
data(){
return{
opacity:1
}
},
activated(){
console.log('News组件被激活了')
this.timer = setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
deactivated(){
console.log('News组件失活了')
clearInterval(this.timer)
}
}
</script>
13.路由守卫
作用:
对路由进行权限控制
分类:
全局守卫
// 全局前置守卫:初始化时、每次路由切换前执行
router.beforeEach((to,from,next) => {
console.log('beforeEach',to,from)
if(to.meta.isAuth){ // 判断当前路由是否需要进行权限控制
if(localStorage.getItem('school') === 'atguigu'){ // 权限控制的具体规则
next() // 放行
}else{
alert('暂无权限查看')
}
}else{
next() // 放行
}
})
// 全局后置守卫:初始化时、每次路由切换后执行
router.afterEach((to,from) => {
console.log('afterEach',to,from)
if(to.meta.title){
document.title = to.meta.title //修改网页的title
}else{
document.title = 'vue_test'
}
})
独享守卫
beforeEnter(to,from,next){
console.log('beforeEnter',to,from)
if(localStorage.getItem('school') === 'atguigu'){
next()
}else{
alert('暂无权限查看')
}
}
组件内守卫
//进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {... next()},
//离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {... next()},
14.路由器的两种工作模式
1.对于一个url来说,什么是hash值?
#及后面的内容就是hash值
2.hash值
不会包含在HTTP请求中,即:hash值不会带给服务器
3.hash模式
地址中永远带着#号,不美观
若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
兼容性较好
4.history模式
地址干净,美观
兼容性和hash模式相比略差
应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题
const router = new VueRouter({
mode:'history',
routes:[...]
})
export default router
5.1Vue UI组件库
常用的UI组件库
移动端 | PC端 |
---|---|
Vant | Element UI |
Cube UI | IView UI |
Mint UI | |
NutUI |
Element UI
安装:
npm i element-ui -S
使用:
全部样式:
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'; // 引入ElementUI组件库
import 'element-ui/lib/theme-chalk/index.css'; // 引入ElementUI全部样式
Vue.config.productionTip = false
Vue.use(ElementUI) // 使用ElementUI
new Vue({
el:"#app",
render: h => h(App),
})
按需引入:
安装:
npm i babel-plugin-component -D
修改babel-config-js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
["@babel/preset-env", { "modules": false }]
],
plugins: [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
使用:
import Vue from 'vue'
import App from './App.vue'
import { Button,Row } from 'element-ui' // 按需引入
Vue.config.productionTip = false
Vue.component(Button.name, Button);
Vue.component(Row.name, Row);
/* 或写为
* Vue.use(Button)
* Vue.use(Row)
*/
new Vue({
el:"#app",
render: h => h(App),
})