vue3 新特性

1 创建工程

   vue-cli v4.5/  vite

vite为何启动快?

开发环境使用ES6 Module,无需打包;但是生产环境使用rollop,并不会快很多。

webpack需要转es5。
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')

2 setup

this 为 undefined,可通过 getCurrentInstance() 获取组件实例。

    export default {
        name:'App',
        components:{Demo},
        props:['msg','school'],//props如果不声明接收,值会在$attrs(vue2)
		emits:['hello'],//子组件向父组件传值要声明emit(vue2)
        //在beforeCreate之前执行一次,this是undefined
		setup(props,context){//context为上下文对象,包含attrs/slots/emit(同vue2)
			//数据
			let name = '张三'
			let age = 18

			//方法
			function sayHello(){
				alert(`我叫${name},我${age}岁了,你好啊!`)
			}
			//返回一个对象(常用)
			return {
				name,
				age,
				sayHello,
			}
		}
	}

3 常用组合式API

3.0 模拟vue3实现响应式

实现原理:

通过Proxy(代理):  拦截对象中任意属性的变化, 包括:属性值的读写、属性的添加、属性的删除等。

通过Reflect(反射):  对源对象的属性进行操作。

            //proxy增删改属性都能获取到;Object移植到Reflect:
			//#region 
			const p = new Proxy(person,{
				//有人读取p的某个属性时调用
				get(target,propName){
					console.log(`有人读取了p身上的${propName}属性`)
                    //return target[propName]
					return Reflect.get(target,propName)
				},
				//有人修改p的某个属性、或给p追加某个属性时调用
				set(target,propName,value){
					console.log(`有人修改了p身上的${propName}属性,我要去更新界面了!`)
                    //target[propName] = value
					Reflect.set(target,propName,value)
				},
				//有人删除p的某个属性时调用
				deleteProperty(target,propName){
					console.log(`有人删除了p身上的${propName}属性,我要去更新界面了!`)
                    //return delete target[propName]
					return Reflect.deleteProperty(target,propName)
				}
			})
			//#endregion

3.1 ref和reactive

ref函数

ref函数用来定义一个响应式的数据。(基本数据)通过.value修改值

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

对象类型的数据:内部求助了Vue3.0中的一个新函数—— reactive函数。





why .value

vue3用了proxy实现响应式,那如果用reactive定义引用类型的话是正常的,如果用ref是一个基本类型的值,就没办法实现proxy的拦截,所以vue3中对ref定义的值进行了包装,变成一个对象实现proxy进行拦截达到响应式。

reactive函数

reactive函数定义一个对象类型的响应式数据(深层次的)。

接收一个对象或数组,返回一个proxy对象。

内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。





vue3 新特性_第1张图片

3.2 toRef和toRefs

toRef:创建一个 ref 对象,返回ObjectRefImpl对象,用于将响应式对象中的某个属性单独提供给外部使用。两者保持引用关系

toRefs:批量创建多个 ref 对象。





vue3 新特性_第2张图片

why toRef

对象数据分解

3.3 computed





vue3 新特性_第3张图片

age1具有响应式 

3.4 watch和watchEffect

watch

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

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





watchEffect

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

watchEffect:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。初始化时执行一次,用于收集要监听的数据。





3.5 生命周期

销毁阶段的两个名字改了,创建阶段的2个钩子在setup中调用。




3.6 provide/inject

//祖组件
setup(){
   ......
   let car = reactive({name:'奔驰',price:'40万'})
   provide('car',car)
   ......
}

//后代组件
setup(props,context){
   ......
   const car = inject('car')
   return {car}
   ......
}

3.7 自定义hook函数

本质是一个函数,把setup函数中使用的Composition API进行了封装,类似于vue2.x中的mixin。

import {reactive,onMounted,onBeforeUnmount} from 'vue'
export default function (){
	//实现鼠标“打点”相关的数据
	let point = reactive({
		x:0,
		y:0
	})

	//实现鼠标“打点”相关的方法
	function savePoint(event){
		point.x = event.pageX
		point.y = event.pageY
		console.log(event.pageX,event.pageY)
	}

	//实现鼠标“打点”相关的生命周期钩子
	onMounted(()=>{
		window.addEventListener('click',savePoint)
	})

	onBeforeUnmount(()=>{
		window.removeEventListener('click',savePoint)
	})

	return point
}






4 其他组合式API

shallowReactive 与 shallowRef

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

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

readonly 与 shallowReadonly 

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

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

toRaw 与 markRaw 

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

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

customRef 





响应式数据的判断

isRef: 检查一个值是否为一个 ref 对象

isReactive: 检查一个对象是否是由 `reactive` 创建的响应式代理

isReadonly: 检查一个对象是否是由 `readonly` 创建的只读代理

isProxy: 检查一个对象是否是由 `reactive` 或者 `readonly` 方法创建的代理

5 新组件

Fragment

在Vue2中: 组件必须有一个根标签

在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中

好处: 减少标签层级, 减小内存占用

vue3 新特性_第4张图片

Teleport

 `Teleport` 是一种能够将我们的组件html结构移动到指定位置的技术。


  	

我是一个弹窗

 Suspense

异步渲染子组件:通过插槽控制显示





6 其他改变

  • createAPP

vue3 新特性_第5张图片

  • emits属性

        子组件需要声明自定义事件;

vue3 新特性_第6张图片

  • 多事件处理

vue3 新特性_第7张图片

  • 移除.sync 

vue3 新特性_第8张图片

  • 异步组件

vue3 新特性_第9张图片

  •   移除过滤器

        可以用computed实现

  •  移除keyCode修饰符;修改过渡类名。

7 vue3速度更快 

  1. Proxy响应式

        按需实现深度监听

     2. PatchFlag & hoistStatic & cacheHandler

        https://vue-next-template-explorer.netlify.app

vue3 新特性_第10张图片

        PatchFlag:编译模板时,给动态节点做标记,如TEXT/ CLASS/ PROPS。diff算法根据标记做对比。

        hoistStatic:将静态节点的定义,提升到父作用域,缓存起来;多个相邻的静态节点合并。

        cacheHandler:事件缓存。

     3.SSR优化

        静态节点直接输出,绕过了vdom

    4. tree shaking

        编译时,根据不同的情况,引入不同的API

8 vue中使用JSX

8.1 基本使用



//.jsx文件
import { defineComponent } from 'vue'

export default defineComponent({//传递setup函数或组件配置
    props: ['a'],
    setup(props) {
        const render = () => {
            return 

Child {props.a}

} return render } })

8.2 对比template&JSX

JSX本质是js代码,可以使用js的任何能力

template只能嵌入简单的js表达式,其他需要指令,如v-if

template JSX
插值 {{ msg }} { msg }
组件定义 大小写 大写
属性 :name="name" name={name}
事件 @click="demo(123)" onClick={()=>demo(123)}
条件 v-if

{flagRef.value && }

循环 v-for

{state.list.map(item =>

  • {item}
  • )}

    插槽 v-slot 通过函数传参实现
    import { defineComponent } from 'vue'
    import Child from './Child'
    
    export default defineComponent(() => {
        function render(msg) {
            return 

    msg: {msg} 123123

    } return () => { return <>

    Demo - JSX

    } }) import { defineComponent, ref } from 'vue' export default defineComponent({ props: ['render'], setup(props) { const msgRef = ref('作用域插槽 Child - JSX') return () => { return

    {props.render(msgRef.value)}

    } } })

    script setup(v3.2)

    定义属性defineProps;定义事件defineEmits;defineExpose暴露数据给父组件

    
    
    
    
    
    
    
    Child2.vue
    
    
    
    
    
    Child3.vue
    
    
    

    你可能感兴趣的:(vue,vue.js)