vue3学习笔记

npm搭建项目

安装或升级@vue/cli

npm install -g @vue/cli

查看版本@vue/cli

vue --version

vue create hello-world

npm run serve

报错

Cannot find module 'vue-loader-v16/package.json'

//解决办法

//先卸载vue-loader-v16依赖    

npm uninstall vue-loader-v16

//使用cnpm安装vue-loader-v16依赖    

cnpm i vue-loader-v16

Vite 搭建项目

npm init vite-app <project name>

npm install

npm run dev

setup

Vue3中新的配置项,值为一个函数

组件中用到的数据,方法等,均要配置在setup中

setup函数的两种返回值

  1. 若返回一个对象,则对象中的属性,方法在模板中可直接使用
  2. 若返回一个渲染函数,则可以自定义渲染内容
import {h} from 'vue'
return ()=> h('h1','HelloWorld')

vue2.x配置(data,methods....)中可以访问setup中的属性,方法

但在setup中不能访问到vue2.x配置(data,methods....)

如果有重名setup优先

在beforeCreate之前执行一次,this是undifined:

  • props:值为对象,包含:组件外部传递,组件内部声明接收
  • context:上下文对象
    • attrs:值为对象,包含:组件外部传递,但没有在props配置中声明的属性,相当于this.$attrs
    • slots:插槽内容,相当于this.$slots
    • emit:自定义事件的函数,相当于this.$emit

ref函数

定义一个响应式数据

js中操作数据:xxx.value

模板中读取数据:<div>{{xxx}}</div>

接收的数据可以是基本数据类型,也可以是对象类型

基本类型的数据:响应式依然是靠Object.defineProperty()的get与set完成的

对象类型的数据:内部"求助"了Vue3.0中的reactive函数

reactive函数

定义一个对象类型响应式数据

通过使用Proxy来实现响应式,并通过Reflect操作源对象内部的数据。

vue3.0中的响应式原理

vue2.x的响应式

实现原理:

  • 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截。
  • 数组类型:通过重写更新数组的一系列方法来实现拦截。
Object.defineProperty(data,'count',{
get(){},
set(){}
})

vue3.0的响应式

实现原理:

  • 通过proxy(代理):拦截对象中任意属性的变化,包括:属性的读写、添加、删除等
  • 通过reflect(反射):对被代理对象的属性进行操作
// 源数据
let person = {
	name: 'jan',
	age: 18
}
const p = new Proxy(person, {
	get(target, propName) {
		// console.log(target, propName)
		return target[propName]
	},
	set(target,propName,value) {
		target[propName] = value
	},
	deleteProperty(target,propName){
		return delete target[propName]
	}
})

computed函数

与vue2中的配置一致

let fullName = computed(() => {
	return person.firstName + '-' + person.lastName
})
let fullName = computed(() => {
	get() {
			return person.firstName + '-' + person.lastName
		},
		set(val) {
			const nameArr = val.split('-')
			person.firstName = nameArr[0]
			person.lastName = nameArr[1]
		}
})

watch函数

与vue2中的配置一致

监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启深度监听(deep配置失效)

监视reactive定义的响应式数据中某个属性时:deep配置有效

//监听ref定义的响应式数据
watch(count, (newVal, oldVal) => {
	console.log(newVal, oldVal)
},{immediate:true})
// 监听ref定义的多个响应式数据
watch([count,count], (newVal, oldVal) => {
	console.log(newVal, oldVal)
},{immediate:true})
//监听reactive定义的响应式数据的全部属性
watch(person, (newVal, oldVal) => {
	console.log(newVal, oldVal)
},{deep:true})//此处deep配置无效
//监听reactive定义的响应式数据的某个属性
watch(()=>person.age, (newVal, oldVal) => {
	console.log(newVal, oldVal)
})
//监听reactive定义的响应式数据的某些属性
watch([()=>person.age,()=>person.name], (newVal, oldVal) => {
	console.log(newVal, oldVal)
})
//特殊情况:监听reactive定义的对象中的某个属性
watch(()=>person.job, (newVal, oldVal) => {
	console.log(newVal, oldVal)
},{deep:true})

watchEffect函数

watch:既要指明监视的属性,也要指明监视的回调

watchEffect:不用指明监视哪个属性,监视的回调中用到哪个属性

watchEffect注重的是过程(回调函数的函数体),不用写返回值

// watchEffect
watchEffect(()=>{
	const x1 = count.value
	console.log('watchEffect所指定的回调执行了')
})

生命周期

vue2:Vue 实例 — Vue.js

vue3:应用 & 组件实例 | Vue.js

组合式 API:

import {
		onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted
	} from 'vue'

onBeforeMount(()=>{
	console.log('-- onBeforeMount --')
})
onMounted(()=>{
	console.log('-- onMounted --')
})
onBeforeUpdate(()=>{
	console.log('-- onBeforeUpdate --')
})
onUpdated(()=>{
	console.log('-- onUpdated --')
})
onBeforeUnmount(()=>{
	console.log('-- onBeforeUnmount --')
})
onUnmounted(()=>{
	console.log('-- onUnmounted --')
})

其他Composition API

shallowReactive与shallowRef

shallowReactive:只处理对象最外层属性的响应式(浅响应式)

shallowRef:只处理基本数据类型的响应式,不处理对象的响应式

如果有一个对象数据,结构比较深,但变化时只是外层属性变化,用shallowReactive

如果有一个对象数据,后续功能不会修改该对象中的属性,而是生成新的对象来替换,用shallowRef

readonly与shallowReadonly

readonly:让一个响应式数据变为只读(深只读)

shallowReadonly:让一个响应式数据变为只读(浅只读)

toRaw与markRaw

toRaw:将一个reactive的响应式对象转为普通对象

        用于读取响应式对象的普通对象,对这个普通对象的所有操作,不会引起页面更新

markRaw:标记一个对象,使其永远不会再成为响应式对象

        有些值不应被设置为响应式的,例如复杂的第三方类库

        当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能

customRef

创建一个自定义ref,并对其依赖项跟踪和更新触发进行显式控制

setup(){
	let keyword = myRef('hello')//使用自定义ref
	function myRef(val){
		return customRef((track,trigger)=>{
			return{
				get(){
					track()
					return val
				},
				set(value){
					val = value
					trigger()
				}
			}
		})
	}
	return {
		keyword
	}
}

provide与inject

实现祖孙组件间通信

父组件有一个provide选项来提供数据,子组件有一个inject选项来开始使用这些数据

//祖组件中
setup(){
    let car = reactive({name:'特斯拉',price:'40W'})
    provide('car',car)
}
//孙组件中
setup(){
    let car = inject('car')
    return {car}
}

响应式数据的判断

isRef    //判断是否是ref对象
isReactive    //判断是否是reactive创建的响应式代理
isReadonly    //判断是否是readyonly创建的只读代理
isProxy    //判断是否是reactive或readonly方法创建的代理

新的组件

Fragment

  • 在vue2中,组件必须有一个根标签
  • 在vue3中,组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中
  • 减少标签层级,减少内存占用

Teleport

能够将组件html结构移动到指定位置

<!-- to="移动位置" -->
<teleport to="">
    <div v-if="isShow">
        <div>
            <h3>我是一个dialog</h3>   
            <button @click="isShow=false">关闭dialog</button>
        </div>
    </div>
</teleport>

Suspense

等待异步组件时渲染一些额外内容

//异步引入组件
import {defineAsyncComponent} from 'vue'
const HelloWorld = defineAsyncComponent(()=>{import('./components/HelloWorld.vue')})
//使用Suspense包裹组件,并配置好default与fallback
<Suspense>
	<template v-slot:default>
		<HelloWorld />
	</template>
	<template v-slot:fallback>
		<h5>加载中...</h5>
	</template>
</Suspense>

其他

全局API的转移

vue2有许多全局API和配置

//注册全局组件
Vue.component('myButton',{
    data:()=>({count:0}),
    template:`<button @click="count++">{{count}}</button>`
})
//注册全局指令
Vue.directive('focus',{
    inserted:el=>el.focus()
})

vue3将全局API调整到应用实例(app)上

Vue.prototype -- app.config.globalProperties

其他改变

  • data选项应始终声明为一个函数
  • 过渡类名的更改
/*vue2.x写法*/
.v-enter,
.v-leave-to{
    opacity:0;
}
.v-enter-to,
.v-leave{
    opacity:1;
}
/*vue3.0写法*/
.v-enter-from,
.v-leave-to{
    opacity:0;
}
.v-enter-to,
.v-leave-from{
    opacity:1;
}
  • 移除keyCode作为v-on的修饰符,同时也不再支持config.keyCodes
  • 移除v-on.native修饰符
//父组件中绑定事件
<my-component 
    v-on:close="handleComponentEvent"
    v-on:click="handleNativeClickEvent"
/>
//子组件中声明自定义事件
<script>
export default{
    emits:['close']
}
</script>
  • 移除过滤器(fillter)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值