Vue2复习
JavaScript基础知识
- ES6语法规范
- ES6模块化
- 包管理
- 原型、原型链
- 数组
- axios
- promise
组件化开发
数据—->虚拟DOM—>真实DOM
Vue模板语法
- 插值:
{{}}
指令:
v-bind
,单向绑定v-mode
,用于表单,双向绑定
el和data的两种写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30// el
new Vue({
el: "#app",
data: {
value: 123
}
})
new Vue({
data: {
value: 123
}
}).$mount('#app')
//data
new Vue({
el: "#app",
data: {
value: 123
}
})
new Vue({
el: "#app",
data(){
return{
value:123
}
}
})
MVVM
View ViewModel model
DOM
数据代理
通过一个对象代理对另一个对象中属性的操作
1 | <script> |
事件
@click
@scroll 滚动条
@wheel 滚轮 @wheel.passive 阻止回调函数,让默认行为先执行
事件修饰符
prevent stop once capture self passive
键盘事件
enter deleter esc space tab up down left right配和keyup
ctrl alt shift meta配合keydown
1 | <input type="text" placeholder="请输入" name="" id="" @keyup.right="showInfo"> |
计算属性
可被缓存、直接读取相当于属性
监视属性
1 | <script> |
Style样式
- class
:class="xxx"
,xxx可以是字符串,对象数组 - style
:style="{}"
,:style="[]"
条件渲染
v-if
: 销毁和创建,文档中不存在v-show
:调整display:none/block,还存在于文档中
变化频繁使用v-show
template 不会被渲染,但是能配合
v-if
1 | <template v-if=""> |
v-for key
可遍历数组,对象,字符串,范围(0-10)
如果值是展示类表则可以用index作为:key
如果用输入框,删除等操作,则必须要用唯一标识
响应式 Vue.set()
Vue会监视data中所有层的数据
vue2的响应式是通过object.defineproperty实现的,JavaScript对象传入vue实例时,vue会遍历对象的所有property,并通过object.defineproperty把这些property转化为getter和setter,数据发生变化时,就会触发视图的更新;不过这种方式有点缺陷,就是不能监测到对象属性的添加和删除,因此需要用vue.set()来添加和删除。并且也不能监听数组的变化后添加的数据做响应式
vue.set(target,key,val)方法target不能是Vue实例,或者Vue实例对象的根数据对象
Vue.set(target,key,val)
,vm.$set(target,key,val)
过滤器
不会改变原始数据1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 局部
filters: {
timeFormat(value, str = 'YYYY-MM-DD HH:mm:ss') {
return dayjs(value).format(str)
},
/* mySlice(value) {
// 1970 - 07 - 27 10: 33: 59
return value.slice(0, 4)
} */
}
// 全局过滤器
Vue.filter('mySlice', function (value) {
return value.slice(0, 4)
})
指令梳理
v-bind
v-model
v-for
v-if>
v-else-if
v-else
v-show
v-text
会替换标签中的所有内容
v-html
- 可识别html结构
- 在网站上动态渲染html是非常危险的,容易造成XSS攻击
- 不要在用户提交的内容上渲染
v-clock
1 | <style> |
v-once
初次动态渲染后就会成为静态内容了
v-pre
跳过器所在结点编译过程,跳过没有指令语法的标签
自定义指令
1 | directives:{ |
big函数何时会被调用?指令与元素成功绑定时,指令所在的模板被重新解析时
1 | <input type="text" name="" id="" v-fbind="num"> |
注意:自定义指令里面的this指向windows
全局指令
1 | <p><span v-big="num"></span></p> |
生命周期
1 | <script> |
常用生命周期钩子
- mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息
beforeDestroy: 清除定时器、解绑自定义事件、取消订阅【收尾工作】
关于销毁vue实例
- 销毁后借助vue开发者工具看不到任何消息
- 销毁后自定义事件会失效,但原生dom事件依然存在
- 一般不会再 beforeDestroy 操作数据,因为即便操作数据,也不会触发更新流程
组件化
非单页面组件
使用Vue.extend(options)创建组件
data必须写为函数——-避免组件被复用时,数据存在引用关系
使用template可配置组件的结构
1 | <body> |
- 组件的命名:如MySchool—->my-school,(MySchool需在vue-cli中使用)
- 在html中的写法
</my-school>,</my-school>
组件的嵌套
VueComponent
- 组件中的this指向VueComponent实例对象
- new Vue(options)中的this指向Vue实例对象
内置关系
1 | <script> |
VueComponent.prototype.__proto__==Vue.prototype
单文件组件
Vue-cli(command line interface—命令行结构工具) 脚手架
vue.js
:是完整版Vue,包括核心功能+模板解析器vue.runtime.xxx.js
:运行时的Vue,只包含核心功能
render渲染函数
1 | <script> |
配置文件,输出配置文件
输出配置文件:vue inspect > output.js
配置文件
ref属性
- 被用来给元素或子组件注册引用信息(id的替代者)
- 应用在html标签上获取doc元素,应用在组件上获取实例对象(VueComponent)
- 使用:
<p ref="xxx"></p>
,this.$refs.xxx
props
- 父向子传值
- 只读(不能修改,若业务需要修改,那么复制一份到data中,让后修改data中的数据)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<script>
// 1.简单传值,只做接受
props: ['name', 'age'],
// 2. 限制类型
props: {
name: String,
age: Number
},
// 3. 限制类型,限制必要性,指定默认值
props: {
name: {
type: String,
required: true
},
age: {
type: Number,
default: 99 // 默认值
}
},
</script>
mixin(混入)
- 可以把多个组件的共用配置提取在一个混入对象中
- 定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17export const mixin = {
data() {
return {
x: 10,
y: 20
}
},
methods: {
showName() {
alert(this.name)
}
},
mounted() {
console.log(888888);
},
} - 使用
- 全局引入:
Vue.mixin(xxx)
- 局部引入:
mixins:[xxx,xxx]
- 全局引入:
插件
plugins.js
1 | export default { |
main.js
1 | import Vue from "vue"; |
scoped 样式
让样式局部生效,
<style scoped>
todoList案例
eventBus,消息订阅,Vuex===>兄弟之间数据通信
- 组件化编码流程
- 拆分为各个组件
- 数据传输,共享
- props适用
- 父=====>子
- 子=====>父 通信(要求父先给子一个函数)
- 适用v-model是切记,v-model绑定的值不能是props(只读)传过来的值
- props传过来的若是对象类型,修改的对象中的属性时Vue不会报错,但是不推荐这么做
web Storage
- 存储的内容大小一般为(5MB)左右(依浏览器)
- 浏览器通过,
sessionStorage
,localStorage
,属性实现本地存储 - 相关api:
xxxStorage.setItem('key','val')
设置存储的键值,xxxStorage.getItem('key')
获取键对应的值,xxxStorage.removeItem('key')
移除键值,xxxStorage.clear()
清空存储的所有数据 - 备注:
- sessionStorage存储的内容会随浏览器窗口的关闭而自动清除
- localStorage存储的内容(永久性),需手动清除
getItem('key')
,如果key对应的值不存在则返回null- 若存储的是对象记得用
JSON.Stringify()
转为字符串,使用的时候用JSON.parse()
解析为对象
组件的自定义事件(通信方式)
- 适用于:子—->父
- 第一种:子父组件中
<Demo @test="test"></Demo>
,@test表示子组件的自定义事件,test表示父组件接受的事件 - 第二种
1
2
3mounted(){
this.$refs.xxx.on('xxx',this.test)
} - 若想让自定义事件执行一次需要用
once
,或$once
- 触发自定义事件
this.$emit('xxx',数据)
,解绑自定义事件this.$off('xxx')
- 组件绑定原生DOM事件,需要用native修饰符
- 通过
this.$refs.xxx.$on('xxx',回调)
,回调要么配置在methods中要么用箭头函数,否则this指向会出问题
全局事件总线(GlobalEventBus)
- 适应于任意组之间的同信
安装
1
2
3
4
5
6
7new Vue({
el: '#app',
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this
}
})使用
发送数据
1 | methods: { |
接受数据
1 | mounted() { |
- 最好在
beforeDestroy
中,用$off
解除当前绑定的事件
消息订阅与发布(pubsub)
- 适用于任意组件同信
- 安装:
npm i pubsub-js
,引入:import pubsub from 'pubsub-js'
- 发布消息
1
pubsub.publish('xxx',数据)
- 订阅消息
1
2
3
4
5
6mounted(){
this.pid=pubsub.subscribe('xxx',(msgData,data)=>{
// msgData 订阅号(xxx)
// data 订阅的东西(数据)
})
} - 取消订阅:在
beforeDestroy
里,pubsub.unsubscribe(this.pid)
$nextTick
this.$nextTick(callback)
- 在下一次dom更新后执行其回调
- 当改变数据后,要基于更新后的dom进行某些操作,要用到nextTick
Vue过度和动画
- 内部组件
transition
- 第三方库,
npm install animate.css --save
,animate.css
1
2
3
4<transition-group name="h" appear="">
<h2 v-show="!isShow" key="1" class="rounded">Hello1</h2>
<h2 v-show="isShow" key="2" class="rounded">Hello2</h2>
</transition-group>
配置代理 axios
跨域
- cors
- jsonp
- 代理Proxy nginx 代理服务器反向代理,负载均衡
插槽
子组件挖坑,父组件填坑
- 默认插槽
<slot></slot>
,占位 - 具名插槽
<slot name='xxx'></slot>
- 作用域插槽
<slot :test="test"></slot>
<template scope="getData"></template>
,使用{{getData.data}}
Vuex
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同一状态
1 | import Vuex from 'vuex' |
state
- 全局数据共享状态,相当于data
- 读取数据,映射为计算属性
this.$store.state.num
...mapState({})
对象形式...mapState([])
数组形式getters
- 对state中的数据进行加工,相当于计算属性
- 读取数据
this.$store.getters.xxx
...mapGetters({})
...mapGetters([])
mutations
- 在methods中, 唯一更改store中状态的方法(同步)
- 读取数据
this.$store.commit()
...mapMutations({})
...mapMutations([])
actions
- 用于提交mutation(异步)
- 读取数据
this.$store.dispatch()
...mapActions({})
...mapActions([])
modules
- 将单一的store拆分为多个store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const modeleA = {
state: {
s: 'I am modelueA'
},
getters: {
},
mutations: {
},
actions: {
}
}
const modeluB = {
state: {
},
getters: {
},
mutations: {
},
actions: {
}
}
export default new Vuex.Store({
modules: {
a: modeleA,
b: modeluB
}
})
Vuex模块化+namesapce
开启命名空间
1
2
3
4
5
6
7
8
9
10
11
12const testModule = {
namespaced: true,
state: {
},
getters: {
},
mutations: {
},
actions: {
},
}组件中读取state数据
this.$store.state.testModule.num
...mapState('testModule',['num','xxx'])
- 组件中读取getters数据
this.$store.getters['testModule/xxx']
...mapGetters('testModule',['xxx'])
- 组件中调用commit
this.$store.commit('testModule/xxx')
...mapMutations('testModule',['xxx','xxx'])
- 组件中调用dispatch
this.$store.dispatch('testModule/xxx')
...mapActions('testModule',['xxx','xxx'])
路由
SPA(single page web application)
- 安装:
npm i vue-router@3
Vue2安装3版本 - 应用:Vue.use(VueRouter)
- 配置
1 | import VueRouter from "vue-router"; |
<router-link to="" active-class=""></router-link>
配置路由切换<router-view></router-view>
组件的呈现位置- 每次切换都伴随着组件的销毁和挂载
- 每个组件都有自己的$route属性,记录着自己的路由信息
- 整个应用只有一个router,可以通过组件的$router属性获取
多级路由,嵌套
1
2
3
4
5
6
7
8
9
10{
path: '/home',
name: 'Home',
component: () => import('../views/Home'),
directive: '/message',
children: [
{ path: 'message', name: 'Message', component: () => import('../views/Message') },
{ path: 'news', name: 'News', component: () => import('../views/News') }
]
},<router-link class="nav-link" active-class="active" aria-current="page" to="/home/message">message</router-link>
简化路由
- 给routes里的每一项加name属性
- 原来写法:
<router-link :to="/home/message/detail?id=${lst.id}&title=${lst.title}">{{lst.title}}</router-link>
- 现在写法:
<router-link :to="{name:'detail',query:{id:lst.id,title:lst.title}}">{{lst.title}}</router-link>
路由的参数携带
- query
1 | // 1.直接传递 |
- params
1 | // 1.直接传递 |
- 接收数据🎉
this.$route.query/params.xxx
路由props
1 |
|
1 |
|
</router-link>的replaces属性
- 控制路由跳转是操作浏览器历史记录的模式
- 浏览器的历史记录有两种:
push
,repalce
,push
是追加记录模式,replace
是替换当前记录模式,默认为push - 开启
replace
,<router-link repalce></router-link>
- 就是一个入栈与出站的操作
编程式路由导航
push
,replace
1 | methods: { |
back()
,forward()
,go()
1
2
3
4
5
6
7
8
9
10
11
12
13
14methods: {
// 后退
back() {
this.$router.back()
},
// 前进
forward() {
this.$router.forward()
},
go() {
//前进或,后退n步
this.$router.go(-2)
}
}
缓存
让对应组件路由保持挂载,不销毁
1 | <!-- 缓存include='xxx' xxx是组件名也就是组件中的name属性--> |