基本步骤:
在main.js中导入createApp函数
import {createApp } from 'vue'
定义App.vue根组件,导入main.js
import App from './App.vue'
使用createApp函数基于App.vue组件创建应用实例
const app = createApp(App)
挂载至index.html的#app容器
app.mount('#app')
vue3响应式原理:
vue2响应式原理:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)
vue3响应式原理:通过Proxy(代理)拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等
var book = {
_year : 2004,
edition : 1
}
book.year = 2005;
let proxy = new Proxy(obj, {
get : function (target, prop) {
return target[prop]
},
set : function (target, prop, value) {
target[prop] = value;
if(prop === 'count') {
double = getDouble(value)
}
},
deleteProperty(target, prop) {
delete target[prop]
if(prop === 'count') {
double = NaN
}
}
})
var book = {
_year : 2004,
edition : 1
}
book.year = 2005;
利用原生Object.defineProperty方法
Object.defineProperty(book,"year",{
get(){ //访问book对象中year属性时自动调用的方法,返回值就是拿到的值
return this._year
},
set(newYear){ //设置book对象中year属性时自动调用的函数,属性最新值会当成实参传入
this._year = newYear;
}
})
vue2和vue3区别
vue2:选项(Options)API(易于学习和使用,但是代码组织性差)
vue3:组合(composition)API(体积小,性能提升,更好支持TS)
setup():新的组件选项,组合API的起点,在vue2的beforeCreate前执行,此时this不是组件实例而是undefined,在模板中使用的数据和函数在setup中返回
生命周期钩子函数
setup:创建实例前
onBeforeMount:挂载DOM前
onMounted:挂载DOM后
onBeforeUpdate:更新组件前
onUpdated:更新组件后
onBeforeUnmount:卸载销毁前
onUnmounted:卸载销毁后
reactive函数:只能定义复杂类型数据,成为响应式数据(重点)
先从vue中导入
import { reactive } from 'vue'
然后导入数据
const obj = reactive({
name: 'ls',
})
toRef函数:转换响应式对象中某个属性为单独响应式数据,并且值关联(解构数据不能实现响应式)
先从vue中导入
import { reactive, toRef } from 'vue'
const name = toRef(obj, 'name')
toRef修改数据需要添加value,value是存放值的地方
name.value = 'zs'
toRefs函数:转换响应式中所有属性为响应式数据,用于解构|展开reactive定义对象
先从vue中导入
import { reactive, toRef, toRefs } from 'vue'
const obj1 = toRefs(obj)
转化之后可以返回解构出的对象
toRefs修改数据需要添加value,value是存放值的地方
obj1.name.value = 'zs'
与reactive函数定义数据相通obj.name = 'zs'
也可以
ref函数:定义简单类型数据也可以定义复杂数据类型,成为响应式数据(重点)
修改值需要.value
computed函数:定义计算属性,不能修改
基础用法
const obj = computed( () => {
return 计算值
})
高级用法:支持v-model修改数据
const obj = computed( () => {
get(){ //获取计算属性值
return 计算值 //效果和基础用法相同
}
set(value) { //监听计算属性变化
age.value = value + 2
}
})
watch函数:定义侦听器
监听ref和reactive定义的响应式数据
watch(count, (newVal, oldVal) => {}, {deep: true, immediate: true})
第一个参数是需要监听的对象,第二个参数是改变后触发的函数,第三个参数是个对象,可以设置deep深度监听数据变化和immediate默认执行
监听多个数据变化
watch([count, obj], (newVal, oldVal) => {})
监听对象中某个属性变化需要写成函数返回该属性的方式
watch(() => obj.name, (newVal, oldVal) => {})
ref属性:获取DOM或组件实例
获取单个DOM或组件
先使用ref定义一个空的响应式数据
const dom = ref(null)
setup中返回该数据,想要获取dom元素在该元素上使用ref属性绑定该数据即可
<div ref="dom"></div>
获取v-for遍历的DOM或组件
定义一个空数组接受所有li
const domList = []
定义一个函数,网空数组pushDOM
const setDom = (el) => {
domList.push(el)
}
父子通讯
父传子
父组件定义一个ref数据,使用return返回并使用属性绑定到父组件中的子组件占位符上:money="导出ref对象"
子组件中使用props接收父组件数据,props和setup同级且setup(props)中的props就是父组件数据
子传父
触发自定义事件的时候emit来自setup(props, {emit}){//emit就是触发事件函数}
<Son :money="money" @updata:money="updataMoney" />
简写<Son v-modul:money='money' />
依赖注入:后代组件通讯(单向数据流)
父组件使用provide('约定接收名称', 父组件传递数据对象名或函数名)
子孙组件使用inject('约定接收名称')
语法糖
<Son :modelValue="msg" @update:modelValue="msg=$event" />
vue3封装组件支持v-model的时候父传子:modelValue
子传父@update:modelValue
想获取原生事件对象
绑定是函数fn,fn(e){ //e就是事件对象}
绑定是js表达式,提供一个默认变量$event
<h1 @click="$event.target.style.color='red'">父组件 {{count}}</h1>
想获取自定义事件
绑定是函数fn,fn(data){ //data是触发自定义事件的传参}
绑定是js表达式,$event
代表触发自定义事件的传参
<Son :modelValue="count" @update:modelValue="count=$event" />
vue2
获取单个元素
通过ref属性绑定该元素
<div ref="box"></div>
通过this.$refs.box
获取元素
获取v-for便利的多个元素
通过ref属性绑定被遍历元素
<li v-for="i in 4" :key="i" ref="li"></li>
通过this.$refs.li
获取所有遍历元素
除去v-model实现双向数据绑定的另外方式
<Son :money='money' @updata:money="fn" />
简写<Son :money.sync='money' />
v-modul
和.sync
已经合并成v-modul
指令
语法糖
<c :value="msg" @input="msg=$event" />
mixins语法(vue2中解决逻辑代码冲突问题,vue3组合API解决了问题不推荐使用)
混入(mixin)提供一种灵活的方式来分发vue组件中的可复用功能,一个混入对象可以包含任意组件选项,组件使用混入对象是,所有混入对象的选项将混合进入该组件本身选项中
在main.js中app实例挂在前app.maxin({//可以按照组件setup内容写入)}
模块化之后在模块中暴露出去,使用时在需要使用的组件中import导入,写入mixins: []
与components同级,因为可能不止写入一个逻辑