vue学习

Vue

MVVM

在这里插入图片描述
Model- 模型 :js - data中的数据
view- 视图: dom - 模板
viewmodel -视图模型: vue实例对象

生命周期
  • vue2和vue3生命周期的区别
    vue2 -optionsAPI
new Vue()//初始化  数据代理还未开始
beforeCreate
↓ //初始化 完成数据监测、数据代理
created
↓ //解析模板,生成虚拟DOM,无法显示解析后的页面
beforeMount //无法操作DOM//将内存中的 虚拟DOM 转为真实DOM插入页面($el备份)
mounted //初始化结束  挂载流程结束//数据更新
beforeUpdate  //数据是新的,页面是旧的//生成新虚拟DOM与旧的虚拟DOM进行比较
updated
↓ //销毁实例 this.$destroy()
beforeDestroy //所有指令仍然有效 但数据更新不会触发页面更新
↓
destroyed //所有自定义事件无效(DOM原生事件仍然有效如@click)

其他生命周期钩子
$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,//是否可枚举,默认为false(枚举:能否被遍历获得)
	writable:true//是否可被修改,默认为false
	configurable:true//是否可被删除,默认为false
	get(){
	//age属性被读取
	    //get必须有返回值
		return number //将age绑定成number数据
	}
	set(value){
	//age属性被修改
		number = value //修改number数据形成双向绑定
	}
})

数据代理: 通过一个对象代理对另一个对象中属性的操作
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}} //name直接被添加到vm对象上成为了一个属性

vue中的数据劫持
_data中的数据进行数据劫持,对数据的变化进行监听,才能做到修改数据,页面上跟着改变

事件修饰符
@click.prevent //阻止默认事件
@click.stop //阻止事件冒泡
@click.once //事件只能触发一次
计算属性computed

有缓存:只有在相关的变量发生改变时才会重新执行,其他无关值的改变不会影响
与v-model配合使用时需要定义set(),否则出错

//默认存在get
double(){
	return this.number * 2
}
//相当于
double: {
	get() {
		return this.number * 2
	}
}
//与v-model绑定时由于v-model是双向绑定需要定义set()
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适用进行异步操作

插值表达式语法
//{{ }}只要vue实例中的属性都可以写在插值中
<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//在vue接管的瞬间被删除
v-once//所在节点初始化后,就是静态内容,不会随着数据更新而改变
v-pre//所在节点跳过编译过程,使用在没有指令语法的节点,可以加快编译
  • v-model数据双向绑定
<input type="text" v-model="message" />
//等价于
<input type="text" :value="message" //message改变时value也改变
@input="valueChange" /> //输入value改变时message更新
data(){
	return{
		message:''
	}
}
methods:{
	valueChange(event) {
		this.message = event.target.value
	}
}
  • v-html安全问题
    容易导致xss攻击(冒充用户值守)
    不能用在用户提交的内容上

  • v-cloak
    当遇到js阻塞时,为了防止在vue接管前就已经渲染的画面上出现类似{{xxx.name}}这样未编译的内容
    给对应节点添加v-cloak并给v-cloak添加样式

<style>
	[v.cloak]{display:none;}
</style>
<body>
    <h2 v-cloak>{{name}}</h2>
</body>
  • v-if 和 v-show的区别
    v-if 只渲染符合条件的元素,不符合的不渲染
    v-show两者都渲染,不符合条件的元素设置为display:none
    v-if 与 v-for 不要在一个元素中连用,v-for的执行优先级高于v-if

  • v-for 遍历

//遍历数组
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

//App.vue
<children :list = "list"></children>

data() {
 return{
 	list:[]
 } 
}

//Children.vue
props:{
	list:Array
}

子→父 :emit

//children.vue
data() {
 return{
 	title:''
 } 
}

add(){
	this.$emit('add', this.title)
}
//App.vue
<children @add="add" />

methods:{
	add(){console.log(title)}
}
兄弟通信

$Eventbus

//event-bus.js
import Vue from 'vue';
const eventBus = new Vue(); //创建新的实例
export default eventBus;
//List.vue
import eventBus from './event-bus'
export default {
	mounted(){
		eventBus.$on('funcname',console.log(title)) //接收
	}
}
//input.vue
import eventBus from './event-bus'
export default {
    data(){
    	return{
    		title:''
    	}
    }
	mounted(){
		eventBus.$emit('funcname', this.title) //接收
	}
}
消息订阅与发布

pubsub-js

插槽slot

作用域插槽:在父组件调用子组件slot时,使用子组件变量数据赋值

//Children.vue
<div>
	<slot :title="title">default<slot>
</div>

data() {
 return{
 	title: {
 	  id:'',
 	  title:''
 	}
 } 
}
//App.vue
<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 抽离公共逻辑
//mixin.js
export default{
	data(){
		return {
			commonData:''
		}
	},
	method:{},
	mounted:{}
}
//component.vue
import mixin from './mixin'
export default{
	mixins:[mixin],
	data(){}
}
<div>{{commonData}}</div>
vuex插件

实现集中式状态管理
多组件共享数据(全局单例模式)
在这里插入图片描述不要直接修改state里的数据,而是通过actions/mutations的流程进行修改,以便devtools进行监控

//store/index.js
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')//下一步提交给mutation
					console.log(payload)
					resolve()
				})
		    })
		}
	},
	getters:{ //类似于computed
		return x * x
	},
	module:{  //将store分割成模块
	}
}
//App.vue
methods:{
	add(count){
		this.$store.commit('mufunc', count)
	}
	multi(payload){
		this.$store.dispatch('acUpdate',payload)
		.then(res =>{})
	}
}
  • state单一状态树:只定义一个store
  • module分割成模块:
    在这里插入图片描述
webpack
虚拟DOM与diff算法
试题

参考
参考
参考

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值