vue3 新特性

// 注册全局组件
import HelloWorld from '@/components/HelloWorld.vue'
const app = createApp(App)

//全局挂载属性和方法
// 方法一:
app.config.globalProperties.$Test = () => {
    return '全局挂载属性和方法'
}

// 方法二:提供/注入 后续详细介绍
// app.provide('$Test', 'hi')
app.use(store).use(router).component('HelloWorld', HelloWorld).provide('$Test', 'hi').mount('#app')


// .vue文件

setup(){
	// 接收方法一
	const { ctx } = getCurrentInstance()
    let test1 = ctx.$Test
	// 接收方法二
	let test2 = inject('$Test')
}

setup:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <div @click="plusOne">{{ name }}-{{ age }}</div>
    <Child />
    <HelloWorld msg="Welcome to Your Vue.js App" />
  </div>
</template>



setup(props, context)
// props是一个形参, 组件接收的props数据可以访问到
// context上下文对象,可以通过context来访问vue的实例this
// Attribute (非响应式对象)
    // console.log(context.attrs)

    // 插槽 (非响应式对象)
    // console.log(context.slots)

    // 触发事件 (方法)
    // console.log(context.emit)
	// 也可写成setup(props, { attrs, slots, emit })
 {
	/**
	1、setup函数处于生命周期beforeCreate和Created两个钩子函数之间,无法使用data和methods的数据和方法,this为undefined
	2、setup函数是 Composition API(组合API)的入口
	3、方法和变量需要return出去,不然无法使用
	**/
   
    const { ctx } = getCurrentInstance()
    
    // ref将setup函数声明变为响应式,包含且仅有一个value属性
    let name = ref("xxx");
    let age = ref(18);
    // reactive 为引用类型添加响应式
    let r = reactive({a:1, b: {c:2}})
    function plusOne() {
      age.value ++
    }
	// 使用watch
	watch(age, (newVal, oldVal) => {
      // console.log(newVal, oldVal)
    })
	// 使用computed
	const counter = ref(0)
    const twiceTheCounter = computed(() => counter.value * 2)

    counter.value++
    // console.log(counter.value) // 1
    // console.log(twiceTheCounter.value) // 2

	// 返回的内容整个组件内都可以直接使用
     return {
      name,
      age,
      r,
      plusOne
    };
    onBeforeMount(() => {});
    onMounted(() => {});
    onBeforeUpdate(() => {});
    onUpdated(() => {});
    onBeforeUnmount(() => {});
    onUnmounted(() => {});
    onRenderTracked((key, target, type) =>{
      // console.log({ key, target, type });
    })
    // 可监听到数据改变
    onRenderTriggered(({ key, target, type }) => {
      // console.log({ key, target, type });
    })
  },

provide 和 inject

grdFather.vue
import father from '@/components/father'
import { provide } from 'vue'
export default {
    name: 'grdFather',
    components: {father},
    setup(){
        let grdFather = ref('comefrom grafather')
	    // readonly包裹后可以在组件内引用时不被改变
	    provide('grdFather', grdFather)
	    // provide('grdFather', readonly(grdFather))
    }
}

father.vue
import son from '@/components/son'
import { inject } from 'vue'
export default {
    name: 'father',
    components: {son},
    setup(){
        let value= inject('grdFather')
        console.log(1, value)
        return {
            val
        }
    }
}

son.vue
import { inject } from 'vue'
export default {
    name: 'father',
    setup(){
        let value= inject('grdFather')
        console.log(2, value)
        return {
            val
        }
    }
}

在这里插入图片描述

vue3和vue2的比较

Vue3使用Proxy替代了defineProperty
Object.defineProperty(obj,prop,descriptor) 的问题主要有三个:
obj
要定义属性的对象。
prop
要定义或修改的属性的名称或 Symbol 。
descriptor
要定义或修改的属性描述符。

let myobj = {};
 Object.defineProperty(myobj,"name",{
     configurable:true,//configurable 给的说明是 如果为 false , 那么对象属性不可以修改, 不可以删除. true则相反
     /*enumerable可枚举;
     设置为true后可以用这4种方式去操作属性
     1.
     for(let i in myobj){
         console.log(i);
     }
     2.
     Object.keys();
     3.
     JSON.stringify
     4.
     Object.assign
     */
     enumerable:true, 
    get(){//当获取属性的时候会进入get方法,可以对获取的值进行修改操作后返回 (必须返回值)或者获取的就是 undefined
        //value 内置属性 获取对象属性值
        return value;
    },
    set(newValue){//set方法监听设置的值 newValue参数获取要改变的值
    //value 内置属性 可以对对象属性的做更改
    //value="dd";
      value = newValue;
    }
})
  • 不能监听数组的变化
  • 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历
  • 必须深层遍历嵌套的对象

Proxy(target, handler)的特点:

let myobj = {};
//Proxy必须实例化 返回新的对象
//用起来比较方便 主要传入要劫持的对象,不用每个属性设置劫持
let obj  = new Proxy(myobj,{
    get(target,key){//target 表示当前实例的对象 key 表示获取属性名
     
        console.log("get..")
        return  target[key];
    },
    set(target,key,value){//target 表示当前实例的对象 key 表示获取属性名 value获取当前属性的值
        target[key] = value;
    }
})
  • 针对对象:针对整个对象,而不是对象的某个属性,所以也就不需要对keys进行遍历
  • 支持数组:Proxy不需要对数组的方法进行重载
  • Proxy的第二个参数有13种拦截方法

diff算法
vue2中diff算法思路:
diff算法采用两端比较的算法,同时从新旧VNode的两端开始进行比较,借助key值找到可复用的节点,再进行相关操作。
vue3中diff算法思路:
在创建VNode时就确定其类型,以及在mount/patch的过程中采用位运算来判断一个VNode的类型,在这个基础上再配合核心的diff算法。在创建虚拟dom树的时候,会添加一个PatchFlags(静态标记),进行对比的时候就直接对比带有静态标记的节点。
静态提升
不参与更新的内容节点做静态提升,渲染时直接复用
Tree-shaking友好
常用的API value、computed、watch等都是从vue中使用import引进来的,所以支持tree-shaking。即如果没有使用这些api,那么这些相应的代码就不会被打包,缩小了文件大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值