Vue
MVVM
Model- 模型 :js - data中的数据 view- 视图: dom - 模板 viewmodel -视图模型: vue实例对象
生命周期
- vue2和vue3生命周期的区别
vue2 -optionsAPI
new Vue()
↓
beforeCreate
↓
created
↓
beforeMount
↓
mounted
↓
beforeUpdate
↓
updated
↓
beforeDestroy
↓
destroyed
其他生命周期钩子 $nextTick vue批量异步渲染 $nextTick会在vue异步渲染执行之后再执行,就能获取dom元素属性更新后的数据值 activated/deactivated 路由独有的生命周期钩子,当组件处于可见状态触发 activated 当组件处于不可见状态触发 deactivated vue3 -compositionAPI(新增)
数据代理
Object.defineProperty双向绑定数据
let number = 18
let person = {
name:'',
sex:''
}
Object.defineProperty(person,'age',{
value:19,
enumerable:true,
writable:true,
configurable:true,
get(){
return number
}
set(value){
number = value
}
})
数据代理: 通过一个对象代理对另一个对象中属性的操作 obj2能够修改obj1中的属性数据
let obj = {x:111};
let obj = {y:222};
Object.defineProperty(obj2,'x',{
get(){
return obj.x
}
set(value){
obj.x = value
}
})
vue中的数据代理: vue通过vm对象将data对象中的属性进行代理 vm._data = data 将_data 中的所有属性通过```Object.defineProperty``添加getter和setter添加到vm上 相当于获取data中数据时如果没有数据代理:
{{_data.name}}
有了数据代理
{{name}}
vue中的数据劫持: _data中的数据进行数据劫持,对数据的变化进行监听,才能做到修改数据,页面上跟着改变
事件修饰符
@click.prevent
@click.stop
@click.once
计算属性computed
有缓存:只有在相关的变量发生改变时才会重新执行,其他无关值的改变不会影响 与v-model配合使用时需要定义set(),否则出错
double(){
return this.number * 2
}
double: {
get() {
return this.number * 2
}
}
double:{
get(){
return this.number * 2
},
set(value){
this.number = value / 2
}
}
监听器 watch
watch在监听对象时需要深度监听
data() {
return{
name: 'name',
info: {
hobby: 'hobby'
}
}
}
watch:{
name(newValue, oldValue) {
console.log(...)
}
info: {
handler: function(newValue){
console...
},
deep:true
}
}
两者的区别 1.computed能完成的功能,watch都能完成 2.反之不一定,watch适用进行异步操作
插值表达式语法
<p>{{ number }} </p>
<p>{{ number + 1}} </p>
<p>{{ flag ? 'yes' : 'no'}} </p>
<p>{{ name.split('').reverse().join('')}}<p>
内置指令
v-bind
v-model
v-for
v-on
v-if/v-else
v-show
v-text/v-html
v-cloak
v-once
v-pre
<input type="text" v-model="message" />
<input type="text" :value="message"
@input="valueChange" />
data(){
return{
message:''
}
}
methods:{
valueChange(event) {
this.message = event.target.value
}
}
<style>
[v.cloak]{display:none;}
</style>
<body>
<h2 v-cloak>{{name}}</h2>
</body>
array: [
{id:2,option:1},
{id:1,option:1},
]
<li v-for="(item, index) in array" :key="item.id">
{{index}} - {{item.option}}
</li>
obj:{
name:'',
hobby:''
}
<li v-for="(value, key, index) in obj" :key="key">
{{index}} - {{key}} - {{value}}
</li>
key属性
给节点一个标识 不推荐给key赋值index,效率低 eg.当一组数据,给数据最前方增加一个数据 新增数据变成index为0的节点 vue将更新前后虚拟dom的index:0对比,没法分辨真实dom中的input输入,造成更新后错位,且所有节点无法复用,造成效率低
ref属性
原生js的id替代品获取DOM
this.$ref.name
对于组件而言,id获取的是真实DOM元素 而ref是vc实例
父子通信
父→ 子 :props
<children :list = "list"></children>
data() {
return{
list:[]
}
}
props:{
list:Array
}
子→父 :emit
data() {
return{
title:''
}
}
add(){
this.$emit('add', this.title)
}
<children @add="add" />
methods:{
add(){console.log(title)}
}
兄弟通信
$Eventbus
import Vue from 'vue';
const eventBus = new Vue();
export default eventBus;
import eventBus from './event-bus'
export default {
mounted(){
eventBus.$on('funcname',console.log(title))
}
}
import eventBus from './event-bus'
export default {
data(){
return{
title:''
}
}
mounted(){
eventBus.$emit('funcname', this.title)
}
}
消息订阅与发布
pubsub-js
插槽slot
作用域插槽:在父组件调用子组件slot时,使用子组件变量数据赋值
<div>
<slot :title="title">default<slot>
</div>
data() {
return{
title: {
id:'',
title:''
}
}
}
<children>
<template v-slot:default="props">
{{props.title.id}}
</template>
<children>
具名插槽
<slot name ="name"></slot>
<template v-slot:name></template>
动态组件
不确定需求加载组件顺序时,动态绑定组件
<component :is="组件名"></component>
hash & histroy
location.hash = 'aaa'
history.pushState({},'','aaa')
history.replaceState({},'','aaa')
history.back() = history.go(-1)
history.forward() = history.go(1)
路由v-router
- 懒加载:用到的时候再加载对应界面,提高页面加载效率
将路由对应的组件打包成一个一个js代码块 异步请求: 第一次请求时不希望把所有的js都请求下来,而是用到的时候再请求 通过改变导入组件的方式
import Test from './components/Test';
...
components:{
Test
}
components: {
Test:() => import('./components/Test');
}
-
$route & $router $router 全局路由对象 $route 当前处于活跃的路由 this.$router.push('/home')
this.$router.push({
path:'/profile',
query:{name:''}
})
$route.query.id
-
全局守卫 全局监听路由跳转 router.beforeEach((to, from, next) =>{
document.title = to.meta.title
next()
next('/login')
})
router.afterEach((to, from) =>{
})
独享守卫beforeEnter 组件内守卫beforeRouteEnter -
keep-alive 组件缓存 缓存渲染后的结果,并不销毁
mixin 抽离公共逻辑
export default{
data(){
return {
commonData:''
}
},
method:{},
mounted:{}
}
import mixin from './mixin'
export default{
mixins:[mixin],
data(){}
}
<div>{{commonData}}</div>
vuex插件
实现集中式状态管理 多组件共享数据(全局单例模式) 不要直接修改state里的数据,而是通过actions/mutations的流程进行修改,以便devtools进行监控
const store = new Vuex.store{
state:{
x:1,
},
mutations:{
mufunc(state, count){
state.x += count
}
},
actions:{
acUpdate(context, payload){
return new Promise((resolve,reject) =>{
setTimeout(()=>{
context.commit('mufunc')
console.log(payload)
resolve()
})
})
}
},
getters:{
return x * x
},
module:{
}
}
methods:{
add(count){
this.$store.commit('mufunc', count)
}
multi(payload){
this.$store.dispatch('acUpdate',payload)
.then(res =>{})
}
}
- state单一状态树:只定义一个store
- module分割成模块:
webpack
虚拟DOM与diff算法
试题
参考 参考 参考
|