文章目录
此篇文章主要适用于有vue2基础的,用于回看复习巩固的哦
1.初识Vue
使用Vue:
- 创建实例
- 实例中传入配置对象
- 配置对象的属性:
- el: 模板容器
- data:模板里可以直接使用的数据
- {{ XXX }} :XXX为js表达式 且数据实时动态更新(一边改变另一边也跟着改变)
js表达式:会产生一个值 (可以作为赋值等式的右边)
2.模板语法
- 插值语法
{{XXX}} - 指令语法
- 单向数据绑定:v-bind:value=“xxx” 简写: :value=“xxx” (其中xxx也为js表达式)
- 双向数据绑定: v-model:value=“xxx” 简写: v-model=“xxx” (只用于表单类元素 输出类元素)
3. el和data的两种写法
el
- 创建Vue实例的时候就指定el属性
- 实例的$mount()方法指定
//第二种写法:
const vm = new Vue({
data:{
name:'尚硅谷'
}
})
vm.$mount('#root')
data
- 对象
- 函数:返回对象
4. MVVM模式
Model-View-ViewModel:模型-视图-视图模型
- 模型指的是后端传递的数据
- 视图指的是所看到的页面
- 视图模型是mvvm模式的核心,它是连接view和model的桥梁。
- 两个方向 :
- 模式转化为视图(后端数据–>页面) 通过数据绑定
- 视图转化为模型 (页面–> 后端数据) 通过DOM事件监听
- 而这两个方向都实现的 称为:数据的双向绑定
- 两个方向 :
- Vue管理的函数this指向? 一旦为箭头函数 其this不再指向Vue实例了???
什么是DOM BOM JS???
5. vm
vm作为Vue的实例
- 在配置对象传入的参数最后都会出现在vm之中
vm身上的属性以及Vue原型上的所有属性 最后再Vue模块中都可以直接访问
6. 数据代理
1)Object.defineproperty
用来定义对象的某个属性的特性的
除了属性值 是否可修改 可删除等几种属性 还有get和set方法 用于监视属性值改变之后所调用的函数
Object.defineProperty(person,'age',{
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true //控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
console.log('有人读取age属性了')
return number
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value)
number = value
}
})
2) 数据代理
什么是数据代理?
通过一个对象1代理对另一个对象2属性的操作 (读or写)
也就是原来想更改使用对象1 结果再定义函数里面去更改使用了另一个对象的属性
3)Vue中的数据代理
通过上面我们知道data的数据最后是跑到了vm实例上了
使用的时候 我们是使用了了vm中的数据 那么如何实现通过改变vm中的数据的意图 让data中的数据有所改变呢?
这就涉及到了数据代理
通过vm对象代理data中属性的读和写
基本原理:
- 先通过Object.defineProperty()把data对象属性要添加到vm上
- 然后为每一个vm上的属性指定getter 和setter
- 在指定的getter和setter中修改data对象的属性
阶段性总结1
-
初识Vue(怎么使用
- 创建实例 传入配置对象
- 配置对象指定Vue模板(
el
)和传入数据(data
)
-
el指定:配置对象 实例的
$mount
方法 -
data: 对象式和函数式
-
模板语法
- 插值语法
- 数据绑定 (单向
v-bind
双向v-model
)
-
MVVM
模型
- 后端数据和渲染页面之间的传递关系
- 通过VM实现双向数据绑定
-
vm
- Vue的实例
- data中的数据随后会在存在vm的属性中
- 模板中可以直接访问vm的属性以及
Vue原型
上的属性
-
数据代理
Obejct.defineProperty()
方法- 通过vm对象来为data中的属性进行代理
7. 事件的基本使用
Vue实例中的methods属性进行设置
- 普通函数这里的this指向
vm实例
- 若写为箭头函数则为
window
- 函数参数:
- param (传递的数据 可选值)
- event事件对象
methods:{
/* 参数为event事件对象
* 属性有target
* this指向为vm实例 如果写为箭头函数 则this为window */
/* 函数无需数据代理 */
showParams(param, event){
alert(param);
console.log(event.target.innerHTML);
}
}
标签中绑定
- @click = “xxx”
- @click = “xxx(param)”
2)事件修饰符
- .stop 阻止冒泡 (即子元素触发的事件不会传递到父元素)
- .capture
通常嵌套事件的发生分为捕获和冒泡阶段 一般在冒泡阶段才会执行事件
要是想在捕获的时候执行 则加上capture事件修饰符即可(在父元素上加即可) - .wheel :鼠标滚轮滚一次就触发一次(到底部滚动鼠标滚轮仍然可触发)
- .scroll:不管以什么方法(上下键 鼠标滚轮 鼠标拖动)
使得滚动条滚动即可触发 到底部不能滚动了则不触发 - .once 事件只触发一次
- .prevent:阻止默认行为
- self:只有event.target是当前操作的元素时才触发事件
- passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
细致的点 等待二刷 self passive
3)键盘事件
二刷
8. 计算属性
- 定义:需要已有属性进行获得
- 属性
- 简写
9. 监视属性
- 定义 监视属性 改变时候调用回调函数
- 属性
- 深度监视
- 简写
- 和computed区别 (异步)
10. 绑定样式
- :class = "xxx"xxx为:
- 字符串
- 对象
- 数组(true false)
- :style = “xxx” xxx为:
- 对象
- 数组(元素为对象)
11. 条件渲染
- v-if
- v-else-if=“xxx” v-else
- template
- 直接无
- v-show
- 只是隐藏了
12. 列表渲染
- 基本语法
- 指定key
- 虚拟DOM的id
- 通过这个进行比对
- 如果用index出错:
- 逆序添加
- 输出类元素
- 数据监测
- 深度监测
- 对于对象后添加的元素
- 数组后添加应该用:
- 方法
- Vue.set vm.$set()
13. 收集表单数据
- type为text
- v-model收集到的就是value
- type为radio
- v-model收集到的:value(其需要设置value属性)
- type为 checkbox
- 没有配置value属性 收集到的就是checked布尔值
- 配置了
- 数组: value组成的数组
- 非数组:checked
- 三个修饰符
- lazy
- number
- trim
//阻止点击a标签跳转页面
<a href="www.baidu.com" @click.prevent="show">点我提示信息哦</a>
14. 过滤器
- 作用:格式化显示一些数据
- 配置:
- 全局Vue.filter(“xx”,fn);
- filters属性
- {{xx | 过滤器名}}
- v-bind:“xx | 过滤器名 ”
15. 内置指令
- v-text
- v-html
- v-cloak 接管之后消失
- v-html 安全问题
- v-pre 加快编译
16. 自定义属性
- 定义
- 全局 Vue.directive
- directives
- 函数
- 对象 (三个参数 bind inserted update)
17. 生命周期
- 配置data methods方法 --》 解析模板 --》【更新数据】 --》销毁
- mouted:Vue编译过 操作DOM有效
- 发送ajax 开启定时器 订阅消息 自定义事件等
- beforeDestroy : 关闭定时器 取消订阅消息 解绑自定义事件等
阶段性总结2
- 事件处理
- 绑定事件
- 事件修饰符
- 有关键盘
- 绑定样式
- 条件渲染
- 列表渲染
- 过滤器
- 获取表单数据
- 内置指令
- 自定义指令
- 生命周期
18. 非单组件
- 创建
- vue.extend(options对象)
- 两点注意点
- el
- data
- 注册
- 局部注册
- 全局注册
- 使用
- 标签
- 组件的嵌套
19. 单文件组件
将相关组件拆成文件形式 然后通过export导出 import引入
20. 脚手架
- 定义
- 构建工具
- 生成项目模板
- 搭建
- 下载 npm install -g @vue/cli
- 创建项目 vue create xxx
- 启动 npm run
serve
- 使用细节
- webpack相关配置:
21. ref
ref=“xx”
获取:this.$refs.xx
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button ref="btn" @click="showDOM">点我输出上方的DOM元素</button>
<School ref="sch"/>
</div>
</template>
//引用
console.log(this.$refs.title) //真实DOM元素
console.log(this.$refs.btn) //真实DOM元素
console.log(this.$refs.sch) //School组件的实例对象(vc)
22.props
- 父组件给子组件传数据
- attr=“xx”(子组件标签)
- 前面加冒号 引号里面就变成了js表达式(数)
- props属性进行引用(子组件文件中)
- 数组
- 对象
- 可以是对象嵌套(类型 默认值 必要性的进一步设定)
App.vue
<template>
<div>
<Student name="李四" sex="女" :age="18"/>
</div>
</template>
student.vue
//student.vue
//简单声明接收
// 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
}
}
有关babel介绍:链接
babel:JS编译器
23. mixin混入
- 提取公共数据
- 定义mixin.js
- 引入
- 重名的处理
24. plugins
- 功能:增强Vue
- 定义
- plugins.js
- 参数:
- Vue
- params
- 全局filter(格式化显示数据)
- 全局directive(自定义指令)
- Vue原型上添加数据
- 定义混入
- 引入
- main.js
- import
- Vue.use(plugin, params)
25. scoped
- 私有化
- style标签的属性 避免重名设置css样式
- 可以出现的问题 加上不可以为body设置样式了
26.vuex
- vuex是一个插件 一种组件间通信的方式(多个组件共享数据时使用)
- vue2 需要下载vuex@3(指定版本3)
- 基本使用
- 创建文件store/index.js
- 引入Vue 和 Vuex 插件使用(Vue.use(Vuex))
- 定义三个对象
- actions
- 响应动作
- 方法参数:context(有commit方法来提交给mutations)和传入data)
- mutations(其中)
- 普通方法
- 方法参数:state 和 传入data
- state对象
- 存放公共对象
- getters对象
- 对state再加工(相当于computed)
- 创建并暴露store(new Vuex.store({对象传入}))
- actions
- 在main.js引入store 且作为创建vm时配置对象的属性
- 组件中使用
- state: (vm.)$store.state.xx
- mutations: (vm.)$store. commit(方法,data)
- actions:(vm.)$store.dispatch(方法, data)
- 可见上面使用时候前缀很多 使用起来很麻烦 所以引入map
- 使用
- 在组件中引入各个方法(import {} from “vuex”)
- state和getter数据在compued中
- …mapState(xx) / …mapGetters(xx)
- xx为对象形式或者数组(更简便)
- mutations和actions在methods里面配置
- …mapActions(xx) …mapMutations
- 同样为对象和数组形式
store/index.js
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions——用于响应组件中的动作
const actions = {
/* jia(context,value){
console.log('actions中的jia被调用了')
context.commit('JIA',value)
},
jian(context,value){
console.log('actions中的jian被调用了')
context.commit('JIAN',value)
}, */
jiaOdd(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
}
//准备mutations——用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
//准备state——用于存储数据
const state = {
sum:0 //当前的和
}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
main.js
//创建vm
new Vue({
el:'#app',
render: h => h(App),
store,
beforeCreate() {
Vue.prototype.$bus = this
}
})
组件使用(原始)
<h1>当前求和为:{{$store.state.sum}}</h1>
methods: {
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
}
组件使用(map)
computed:{
//靠程序员自己亲自去写计算属性
/* sum(){
return this.$store.state.sum
},
school(){
return this.$store.state.school
},
subject(){
return this.$store.state.subject
}, */
//借助mapState生成计算属性,从state中读取数据。(对象写法)
// ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),
//借助mapState生成计算属性,从state中读取数据。(数组写法)
...mapState(['sum','school','subject']),
/* ******************************************************************** */
/* bigSum(){
return this.$store.getters.bigSum
}, */
//借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
// ...mapGetters({bigSum:'bigSum'})
//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters(['bigSum'])
},
methods: {
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
}
- 模块化+命名空间
- 将四个对象分别定义在不同js文件中 再统一引入在Vuex.store()配置对象的modules属性
- 注意在不同js文件中需要加入namespaced属性(开启命名空间)
- 使用的时候在原先的数组前再加一个为模块名即可
index.js
person.js
store/index.js
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
import countOptions from './count'
import personOptions from './person'
//应用Vuex插件
Vue.use(Vuex)
//创建并暴露store
export default new Vuex.Store({
modules:{
countAbout:countOptions,
personAbout:personOptions
}
})
组件内使用
1)原始形式
computed:{
personList(){
return this.$store.state.personAbout.personList
},
sum(){
return this.$store.state.countAbout.sum
},
firstPersonName(){
return this.$store.getters['personAbout/firstPersonName']
}
},
methods: {
add(){
const personObj = {id:nanoid(),name:this.name}
this.$store.commit('personAbout/ADD_PERSON',personObj)
this.name = ''
},
addWang(){
const personObj = {id:nanoid(),name:this.name}
this.$store.dispatch('personAbout/addPersonWang',personObj)
this.name = ''
},
addPersonServer(){
this.$store.dispatch('personAbout/addPersonServer')
}
},
2)简化形式
computed:{
//借助mapState生成计算属性,从state中读取数据。(数组写法)
...mapState('countAbout',['sum','school','subject']),
...mapState('personAbout',['personList']),
//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters('countAbout',['bigSum'])
},
methods: {
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
},
27.自定义事件
- 实现子组件给父组件传递数据
- 父组件(接收数据)
- 子组件标签中
- fnName=“fatherFn”
- v-on:fnName=“fatherFn”
- 通过$ refs.xxx.$ on(fnName, fatherFn);
- fatherFn为methods里的函数
- 或者为箭头函数
- 定义fatherFn函数
- 参数 : 为传递过来的数据
- 子组件标签中
- 子组件(发送数据)
- this.$emit(“sonfn”,params)
- this.$off()
- 解绑自定义事件
- 参数:
- 字符串(“sonfn”)
- 数组(多个自定义事件的名字)
- 不传 解绑所有
- this.$destroy
- 销毁组件的实例 之后自定义事件 也不奏效了
接受数据的组件
1)
<template>
<div class="app">
<h1>{{msg}},学生姓名是:{{studentName}}</h1>
<!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 -->
<School :getSchoolName="getSchoolName"/>
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) -->
<Student @atguigu="getStudentName" @demo="m1"/>
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) -->
<Student ref="student" @click.native="show"/>
</div>
</template>
mounted(){
this.$refs.xxx.$on('atguigu',this.test)
}
2)
getSchoolName(name){
console.log('App收到了学校名:',name)
},
getStudentName(name,...params){
console.log('App收到了学生名:',name,params)
this.studentName = name
},
发送数据的组件
<template>
<div class="student">
<button @click="sendStudentlName">把学生名给App</button>
<button @click="unbind">解绑atguigu事件</button>
<button @click="death">销毁当前Student组件的实例(vc)</button>
</div>
</template>
methods: {
sendStudentlName(){
//触发Student组件实例身上的atguigu事件
this.$emit('atguigu',this.name,666,888,900)
// this.$emit('demo')
// this.$emit('click')
},
unbind(){
this.$off('atguigu') //解绑一个自定义事件
// this.$off(['atguigu','demo']) //解绑多个自定义事件
// this.$off() //解绑所有的自定义事件
},
death(){
this.$destroy() //销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不奏效。
}
},
28. 全局事件总线
- 任意组件间通信
- main.js
- beforecreate里面再Vue原型上创建$bus (vm)
- 组件(接收数据)
- mounted钩子 this.$ bus.$ on("name, 回调)
- beforeDestroy钩子中 $off
- 组件(发送数据)
- this.$ bus.$ emit(“name”, params)
main.js
//创建vm
new Vue({
el:'#app',
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线
},
})
接受数据的组件
mounted() {
// console.log('School',this)
this.$bus.$on('hello',(data)=>{
console.log('我是School组件,收到了数据',data)
})
},
beforeDestroy() {
this.$bus.$off('hello')
},
发送数据的组件
methods: {
sendStudentName(){
this.$bus.$emit('hello',this.name)
}
},
29. 消息订阅与发布
- 任意组件间通信
- 下载:npm i pubsub-js
引入: import pubsub from ‘pubsub-js’ - 组件(接收数据)
- mouted钩子中 this.pubId = pubsub.subscribe("name, parmas)
- beforeDestroy钩子 pubsub.unsubscribe(this.pubId)
- 组件(发送数据)
- pubsub.publish("name, fn)
接受数据的组件
mounted() {
// console.log('School',this)
/* this.$bus.$on('hello',(data)=>{
console.log('我是School组件,收到了数据',data)
}) */
this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
console.log(this)
// console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
})
},
beforeDestroy() {
// this.$bus.$off('hello')
pubsub.unsubscribe(this.pubId)
},
发送数据的组件
methods: {
sendStudentName(){
// this.$bus.$emit('hello',this.name)
pubsub.publish('hello',666)
}
},
阶段性总结3
-
ref
属性
- 标签
- 获取
-
props
属性
- 组件标签传递
- 子组件中props属性获取
-
mixin
混入
- mixin.js定义export
- import mixins属性 引入
-
plugin
插件
plugin.js
- 引入
Vue.use
-
自定义事件
@ ` - 接收数据组件 - 发送数据组件
-
全局事件总线
$bus
- main.js
- 接收数据组件
- 发送数据组件
-
消息订阅与发布
pubsub
- 下载引入
- 接受数据组件
- 发送数据组件
nextTick函数
- 下一次更新DOM结束后调用该回调函数
- 参数:回调函数
30. vue的过渡和动画
- 单个元素
- transition标签包含动画标签 指定name属性
- 指定.xx-enter-active xx-leave-active 样式的animation属性( transition)
- 设定选择器keyframe
- 多个元素
- transition-group标签包含动画标签 指定name属性
- 指定类名的animation或者transition属性
- 引入animate.css
- 为transition标签指定 name enter-active-class leave-active-class即可
单个元素
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition name="hello" appear>
<h1 v-show="isShow">你好啊!</h1>
</transition>
</div>
</template>
<script>
export default {
name:'Test',
data() {
return {
isShow:true
}
},
}
</script>
<style scoped>
h1{
background-color: orange;
}
.hello-enter-active{
animation: atguigu 0.5s linear;
}
.hello-leave-active{
animation: atguigu 0.5s linear reverse;
}
@keyframes atguigu {
from{
transform: translateX(-100%);
}
to{
transform: translateX(0px);
}
}
</style>
多个元素
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition-group name="hello" appear>
<h1 v-show="!isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">尚硅谷!</h1>
</transition-group>
</div>
</template>
<script>
export default {
name:'Test',
data() {
return {
isShow:true
}
},
}
</script>
<style scoped>
h1{
background-color: orange;
}
/* 进入的起点、离开的终点 */
.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);
}
</style>
animate.css
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<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>
<h1 v-show="isShow" key="2">尚硅谷!</h1>
</transition-group>
</div>
</template>
<script>
import 'animate.css'
export default {
name:'Test',
data() {
return {
isShow:true
}
},
}
</script>
<style scoped>
h1{
background-color: orange;
}
</style>
配置代理服务器
- 解决请求跨域问题(开启代理服务器进行请求 改变请求路径)
- vue.config.js(devServer对象的proxy属性)
- proxy属性为字符串
- 代理一个
- proxy属性为对象
- 对象下的属性名:请求路径头(端口后的路径)
- 值:对象(target pathRewrite changeOrigin属性)
- proxy属性为字符串
vue.config.js
module.exports = {
pages: {
index: {
//入口
entry: 'src/main.js',
},
},
lintOnSave:false, //关闭语法检查
//开启代理服务器(方式一)
/* devServer: {
proxy: 'http://localhost:5000'
}, */
//开启代理服务器(方式二)
devServer: {
proxy: {
'/atguigu': {
target: 'http://localhost:5000',
pathRewrite:{'^/atguigu':''},
// ws: true, //用于支持websocket
// changeOrigin: true //用于控制请求头中的host值
},
'/demo': {
target: 'http://localhost:5001',
pathRewrite:{'^/demo':''},
// ws: true, //用于支持websocket
// changeOrigin: true //用于控制请求头中的host值
}
}
}
}
代理细节补充
31. vue路由
- main.js
- 引入vue-route(npm的时候要指定安装VueRouter@3 否则不兼容vue2 --> 使用插件应用
Vue.use(VueRouter); - 引入router( route/index.js ) -->作为创建Vue实例的配置对象的属性
- 引入vue-route(npm的时候要指定安装VueRouter@3 否则不兼容vue2 --> 使用插件应用
- router / index.js
- 引入vue-route
- export vueRouter实例
- 创建实例时传配置对象(routes属性 是一个数组 放着一个个对象 又包含着name path component children)
- 组件使用
- router-link标签
- 类比a标签
- to属性:跳转的页面路径
- active
- router-view标签
- 组件显示的位置
main.js
- 组件显示的位置
- router-link标签
//引入VueRouter
import VueRouter from 'vue-router'
//引入路由器
import router from './router'
Vue.use(VueRouter)
//创建vm
new Vue({
el:'#app',
render: h => h(App),
router:router
})
router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../components/About'
import Home from '../components/Home'
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
组件
<!-- Vue中借助router-link标签实现路由的切换 -->
<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
1)多级路由
- children属性(对象数组)
- 特殊点
- 只有一级路由path有/ 其余path属性不包含
- 跳转二级路由 to属性要加上一级路由
一级路由
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
</li>
route/index.js
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
}
]
}
]
})
2)query参数
- to属性(前面加冒号 引号才能为js表达式)
- 字符串写法 :to = “
xxxxxx
”(引号里面还有反引号) - 对象写法 引号里面为对象
- 对象属性有:path query对象
- 字符串写法 :to = “
- 使用 vm.$router.query.xx
- 模板里面就省略vm.啦
- 实例配置对象里面vm为this
<!-- 跳转路由并携带query参数,to的字符串写法 -->
<!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link> -->
<!-- 跳转路由并携带query参数,to的对象写法 -->
<router-link :to="{
path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
}">
<template>
<ul>
<li>消息编号:{{$route.query.id}}</li>
<li>消息标题:{{$route.query.title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
mounted() {
console.log(this.$route)
},
}
</script>
3)命名路由
- 创建vueRouter实例的配置对象 里面的name属性来命名
- 在query参数的to的对象写法 就可以将path替换为name(更方便)
<!-- 跳转路由并携带query参数,to的对象写法 -->
<router-link :to="{
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
}">
4)params参数
- 跳转路由并携带参数
- to两种写法
- 字符串写法 直接在路径后面添加 参数之间通过/隔开
- 对象写法 name属性(不能用path)和params属性(对象)
- 创建vueRouter实例配置对象需要在path进行占位
- 组件使用
- vm.$router.params.xx
{
path:'message',
component:Message,
children:[
{
name:'xiangqing',
//占位
path:'detail/:id/:title',
component:Detail,
}
]
}
<!-- 跳转路由并携带params参数,to的字符串写法 -->
<!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link> -->
<!-- 跳转路由并携带params参数,to的对象写法 -->
<router-link :to="{
name:'xiangqing',
params:{
id:m.id,
title:m.title
}
}">
组件使用
<template>
<ul>
<li>消息编号:{{$route.params.id}}</li>
<li>消息标题:{{$route.params.title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
mounted() {
// console.log(this.$route)
},
}
</script>
不同:
query参数类似get请求 地址栏会显示
params参数类似post请求 地址栏不会显示
5) 路由中的props属性
- 更方便使用query参数和params参数 (简写 没有那么多的前缀)
- 创建vueRouter实例的配置对象中设置props属性
- 对象(其中key-value就会以props形式传递给组件)
- 布尔值 (params参数~)
- 函数
- 参数为$router 这样就可以获取到id和params
//用props属性则可以直接用 this.id取值,而可以不用 this.$route.params.id 取值
//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
// props:{a:1,b:'hello'}
//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
// props:true
//props的第三种写法,值为函数
props($route){
return {
id:$route.query.id,
title:$route.query.title,
a:1,
b:'hello'
}
}
组件使用:
<template>
<ul>
<li>消息编号:{{id}}</li>
<li>消息标题:{{title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
props:['id','title'],
computed: {
// id(){
// return this.$route.query.id
// },
// title(){
// return this.$route.query.title
// },
},
mounted() {
// console.log(this.$route)
},
}
</script>
6)router-link标签的replace属性
- 历史记录有两种模式
- 两种模式回退上一个页面都是从栈顶取对应地址
- push模式 进栈
- replace模式 不如栈(直接替换) 此种情况在下次跳转其他页面就回不到这个路由了(还是栈顶)
7)编程式路由导航
- 替代router-link标签
- 利用vm.$router下的push方法 和 replace方法
methods: {
pushShow(m){
this.$router.push({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
},
replaceShow(m){
this.$router.replace({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
}
},
8) 缓存组件
- 不让组件销毁 保持挂载状态
- 在router-link标签外面套一个keep-alive标签
- keep-alive标签中指定include属性
- include属性:
- 字符串:指定一个
- 数组:指定多个
<!-- 缓存多个路由组件 -->
<!-- <keep-alive :include="['News','Message']"> -->
<!-- 缓存一个路由组件 -->
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
9)两个生命周期钩子
- 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
- 具体名字:
- activated路由组件被激活时触发。
- deactivated路由组件失活时触发。
10) 全局路由守卫
- 在router/index.js中添加两个方法
- router.beforeEach
- 每次路由切换之前会被调用(身份验证功能等…)
- 参数:to from next(放行)
- router.afterEach()
- 每次路由切换之后执行
- 修改title等
- router为创建实例返回的变量
//全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{
console.log('前置路由守卫',to,from)
if(to.meta.isAuth){ //判断是否需要鉴权
if(localStorage.getItem('school')==='atguigu'){
next()
}else{
alert('学校名不对,无权限查看!')
}
}else{
next()
}
})
//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
console.log('后置路由守卫',to,from)
document.title = to.meta.title || '硅谷系统'
})
export default router
11)独享路由守卫
- router/index.js
- 在配置对象添加beforeEnter属性指定
- 可以在每个组件中都添加mata属性
- 存放一些信息
- 比如用来判断是否可以授权通过token
//创建并暴露一个路由器
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) => {
console.log('独享路由守卫',to,from)
if(to.meta.isAuth){ //判断是否需要鉴权
if(localStorage.getItem('school')==='atguigu'){
next()
}else{
alert('学校名不对,无权限查看!')
}
}else{
next()
}
}
},
{
name:'xiaoxi',
path:'message',
component:Message,
meta:{isAuth:true,title:'消息'},
}
]
}
]
})
12)组件守卫
- 在组件配置对象添加两个函数
- beforeRouteEnter(to, from ,next)
- 进入该组件时调用
- beforeRouteLeave(to, from, next)
- 离开该组件时调用
//通过路由规则,进入该组件时被调用
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()
}
13)history
14)element-ui
- 引入
//完整引入
//引入ElementUI组件库
// import ElementUI from 'element-ui';
//引入ElementUI全部样式
// import 'element-ui/lib/theme-chalk/index.css';
//按需引入
import { Button,Row,DatePicker } from 'element-ui';
//关闭Vue的生产提示
Vue.config.productionTip = false
//应用ElementUI
// Vue.use(ElementUI);
Vue.component('atguigu-button', Button);
Vue.component('atguigu-row', Row);
Vue.component('atguigu-date-picker', DatePicker);
- 使用
<template>
<div>
<button>原生的按钮</button>
<input type="text">
<atguigu-row>
<el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="info">信息按钮</el-button>
<el-button type="warning">警告按钮</el-button>
<el-button type="danger">危险按钮</el-button>
</atguigu-row>
<atguigu-date-picker
type="date"
placeholder="选择日期">
</atguigu-date-picker>
<atguigu-row>
<el-button icon="el-icon-search" circle></el-button>
<el-button type="primary" icon="el-icon-s-check" circle></el-button>
<el-button type="success" icon="el-icon-check" circle></el-button>
<el-button type="info" icon="el-icon-message" circle></el-button>
<el-button type="warning" icon="el-icon-star-off" circle></el-button>
<el-button type="danger" icon="el-icon-delete" circle></el-button>
</atguigu-row>
</div>
</template>
<script>
export default {
name:'App',
}
</script>
阶段性总结4
-
nextTick
- 下一次更新DOM值周调用
-
过渡与动画
-
一个元素
transition
标签配置name属性 设置css样式 -
多个元素
transition-group
标签包裹 name属性 设置css样式 (六种 有重合) -
animate.css
- import引入
- 设置对应的name class属性
-
-
路由
-
基本使用
- 引入路由器 创建路由 使用
-
嵌套路由
- children属性
- to属性
- path属性
-
query
参数
- to属性的两种方式
- 使用
$router
下的query属性
-
命名路由
- query to的第二种写法取代path属性
-
params
参数
- 路由中要占位
- to的两种写法
- 只能用name 不能用path
-
props
属性
- 更方便使用参数
- 路由中指定的三种方式
-
router-link 的
replace
属性
- 历史记录的回退
-
编程式路由
- vm.$router下的push和replace方法
-
两个生命钩子
-
全局路由守卫
- 在router/index.js中
router.beforeEach()
和router.afterEach()
- 在router/index.js中
-
独享路由守卫
- 在分别路由配置中
beforeEnter
属性配置
- 在分别路由配置中
-
组件内路由守卫
- 组件中配置
beforeRouterEnter()
和beforeRouterLeave()
- 组件中配置
-