[2] Vue3的产生

186 阅读2分钟

一、为什么要使用Vue3或者说Vue3解决了Vue2什么问题

(1)Vue 2 响应式并不是真正意义上的代理,而是基于 Object.defineProperty() 实现的。

Object.defineProperty() API 并不是代理,而是对某个属性进行拦截,所以有很多缺陷,比如:删除数据就无法监听,需要 $delete 等 API 辅助才能监听到。

(2)Option API 在组织代码较多组件的时候不易维护。

vue2是Option Api ,需要在特定的区域写相同功能的代码,随着代码量的增大,导致后期可维护性低,新增或者修改一个功能,就需要不停地在 data,methods 里跳转写代码,我称之为上下反复横跳

为解决Option Api 带来的问题,因此vue3使用了 composition(组合) API,让相关功能的代码更加有条理的组织在一起。

(3)代码不好复用,Vue 2 的组件很难抽离通用逻辑,只能使用 mixin,带来命名空间冲突以及变量来源不清晰的问题。见二

vue3中的vue-composition-api 使用自定义hooks,可以解决以上2个问题,更适合做逻辑的抽离与服用,更加体现高内聚,和低耦合。

(4)Vue3全部模块使用 TypeScript 重构,对TS的支持更加友好。

二、mixin ->vue composition api

2.1 背景

Vue 2 中逻辑的抽离和复用,使用mixin。由于mixin运行时进行对象的合并,因此存在2个问题:

2.2 问题

存在以下2个问题:

  • 命名空间冲突。 组件里有个变量canSubmit,mixin里也有一个canSubmit,组件引入mixin时,会覆盖掉组件里的变量,出现各种问题。
  • 混入的属性来源不清晰-难以追溯。例如一个组件里使用了多个mixin,你无法知道很快知道某个方法是属于那个mixin的。

2.3 解决

vue-composition-api 使用自定义hooks,存在可以解决以上2个问题,更适合做逻辑的抽离与服用,更加体现高内聚,和低耦合。

  • 解决命名冲突问题 显示命名-利用显示赋值,可以从命名 任何从合成函数返回的方法或者函数,解决覆盖问题。
const { someVar1, someMethod1 } = useCompFunction1();
const { someVar2, someMethod2 } = useCompFunction2();
  • 解决难以追溯问题。 变量显式传递给合成函数-利用变量显示传递给合成函数的防范,有效解决隐士依赖的问题。
setup () { 
    const myLocalVal = ref(0); 
    const { ... } = useCompFunction(myLocalVal);
}

三、改变了那些

片段

多节点了,不用都放到div下。

v-model

双向数据绑定统一使用v-model,移除了v-bind.sync,统一使用v-model:xxx的形式。
当xxx为空时,xxx默认为modelValue。
对于v-model=“xxx” , prop 为xxx,event为update

Vue2.x

<ChildComponent v-model="pageTitle" />
<!-- 是以下的简写: -->
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
  
如果想要更改 prop 或事件名称,则需要在 ChildComponent 组件中添加 model 选项:
<ChildComponent v-model="pageTitle" />

<ChildComponent :title="pageTitle" @change="pageTitle = $event" />

Vue3.x

<ChildComponent v-model="pageTitle" />
<!-- 是以下的简写: -->
<ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event"/>

若需要更改 model 名称,而不是更改组件内的 model 选项,那么现在我们可以将一个 argument 传递给 model:
<ChildComponent v-model:title="pageTitle" />
<!-- 简写: -->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event"/>

vue2 中v-model 中表单

<input v-model="sth" />等于
<input :value="sth" @input="sth = $event.target.value" />
在给 <input /> 元素添加 v-model 属性时,默认会把 value 作为元素的属性,然后把 'input' 事件作为实时传递 value 的触发事件

<div id="app">
    <!--v-model title值变了会影响input的value,input中value值变了,会影响title-->
    <!--<input v-model="title" type="text">
    {{ title }}-->

    <!--:value="title"是title值变了会改变输入框的值,但是输入框的值变了不会改变title。
    @input是input框中的值变化时触发的函数,从而改变title。 -->
    <input :value="title" type="text" @input="setTitle" >
    {{ title }}
</div>
<script>
    const App = {
        data () {
            return {
                title: ''
            }
        },
        methods: {
            setTitle(event) {
                this.title = event.target.value;
                console.log(event)
            }
        }
    }
   
</script>

非兼容用于自定义组件时,

  • prop:value -> modelValue;
  • event:input -> update:modelValue;

Vue2.x: v-model = value prop + input event

Vue3.x: v-model = modelValue prop + update event

非兼容:v-bind.sync 被移除,统一用v-model:xxx

new:可多个v-model绑定在组件上

new:添加了自定义v-model修饰符的能力,方法是增加xxxModifiers的属性

v-if v-for

vue2 : v-for 优先级大于 v-if 因此我们不建议一起使用,因为都会遍历然后再去除,性能差。

vue3: v-if 优先级 v-for

即使这样,由于语法上存在歧义,依然不建议同一元素上同时使用两者。

比起在模板层面管理相关逻辑,更好的办法是通过创建计算属性筛选出列表,并以此创建可见元素

data

一句话:data强制返回一个对象的函数,而不是一个对象

Vue.createApp({
   // Vue 3.x中 错误!!
   data: {}
})

mixin data合并规则变动

深层次合并 ——> 浅层次执行合并

过滤器

一句话:vue3.x去掉过滤器,推荐用computed或者method来代替。