【vue3.0】vue3.0与vue2.x的比较

前言

基于vite 搭建的vue3.0项目看上去更优化;vue版本自动3.0版本

npm create vite@latest
yarn create vite
pnpm create vite

在这里我们都使用vue-cli搭建项目,方便对比。

一、主要内容–初步

项目搭建

脚手架搭建 【vue@2、@3】 项目命令一样,在选择是选择对应预设;

vue create hello-vue2
vue create hello-vue3

入口文件

vue@2:

import Vue from 'vue'
new Vue({
  render: h => h(App)
}).$mount('#app') //替换'#app'

vue@3:

import { createApp } from 'vue'

createApp(App).mount('#app') //挂载'#app'

App.vue

  • vue3.0中入口文件使用mount( 挂载 ),不同于vue@2.x的$mount( 替换 );
  • template标签中不在需要一个根元素;为了便于区分,子组件还是推荐一个根元素。
// @2会整个替换,@3只会覆盖内部,虽然一般我们不会改动index.html
<div id="app">
	<p>vue@3中只有我会被替换</p>
</div>

createApp(App)

createApp( ):第一个参数为根组件选项对象,如App;

  • 这个方法在入口文件在传入的是App完整的组件选项对象;
  • 也可以在子组件中只传入html标签以外的组件选项对象,比如给当前子组件,这样就不会替换当前子组件的html内容;
// 这个data会作用于'#list-rendering'
const ListRendering = {
  data() {
    return {
      todos: [
        { text: 'Learn JavaScript' },
        { text: 'Learn Vue' },
        { text: 'Build something awesome' }
      ]
    }
  }
}

Vue.createApp(ListRendering).mount('#list-rendering')

生命周期

创建前后:beforeCreate、created
挂载前后:beforeMount、mounted
更新前后:beforeUpdate、updated
销毁前后:beforeDestroy、destroyed(vue@2
移除前后:beforeUnmount、unmounted(vue@3)
在这里插入图片描述

二、主要内容–使用中

v-show

共同点:v-show 不支持 template 元素,也不支持 v-else

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>

不同点:当 v-if 与 v-for 一起使用时(都不推荐这样用)

  • vue@2:v-for 具有比 v-if 更高的优先级
  • vue@3:v-if 具有比 v-for 更高的优先级,v-if 将没有权限访问 v-for 里的变量;
<template v-for="todo in todos" :key="todo.name">
  <li v-if="!todo.isComplete">
    {{ todo.name }}
  </li>
</template>

v-for 与 in、of

效果都一样,习惯上v-for in 遍历普通对象,v-for of 遍历数组;

  • 遍历数组:(item,index)只有两个参数对应:数组子项、索引;
  • 遍历对象:(value,name,index)可有三个参数对应:属性值、属性名、索引;

非prop的属性在自定义组件中

1、默认情况:都是加在自定义组件的根元素上,可以通过inheritAttrs: falsev-bind="$attrs"实现将传入的属性加到指定元素上;
2、$attrs:包含所有非prop的属性,包括 class、style等;

vue@2:

  • 对于class、style属性:会合并;
  • 对于非上述属性,外部传入会替换组件内属性值;

vue@3:

  • 对于class、style属性:会合并;
  • 对于非上述属性,以内部原有为优先;
  • 特殊地,因为vue@3支持组件中没有根元素,所以如果是自定义组件没有根元素,就不会有默认情况;必须借助$attrs指定要绑到元素,否则警告。

多事件处理

vue@3:新增触发多个事件;
注意:多事件,必须是绑定方法,而不是方法名

<!-- 这两个 one()two() 将执行按钮点击事件 -->
<button @click="one($event), two($event)">
  Submit
</button>
<!-- 这里都不触发 -->
<button @click="one, two">
  Submit
</button>

子组件事件抛出

vue@3:子组件中新增组件选项emits: ['enlargeText'],用于检验抛出的事件

app.component('blog-post', {
  props: ['title'],
  emits: ['enlargeText'],
  template: `
    <div class="blog-post">
      <h4>{{ title }}</h4>
      <button @click="$emit('enlargeText')">
        Enlarge text
      </button>
    </div>
  `
})

在组件中使用v-model

vue@2:与效果原生一致,v-model='[变量名]'

<custom-input v-model="searchText"></custom-input>
//解析后
<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>
//子组件
Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

vue@3:支持参数:v-model:[参数名]

  • 不写参数的话,内部默认使用使用 modelValue 作为 prop 和 update:modelValue 作为事件
  • 可以通过v-model:【参数名】修改默认,这样就可以在自定义组件上绑定多个v-model:new、v-model:new2、...
  • 区分v-model.capitalize这是自定义的修饰符;
//默认解析后
<custom-input
  :model-value="searchText"
  @update:model-value="searchText = $event"
></custom-input>
//默认子组件应该这样写
app.component('custom-input', {
  props: ['modelValue'],
  emits: ['update:modelValue'],
  template: `
    <input
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)"
    >
  `
})

v-model的修饰符

vue@2:支持.trim、.number 和 .lazy
vue@3:

  • 支持.trim、.number 和 .lazy
  • 还支持自定义修饰符,与在组件使用v-model一样需要子组件配合;
  • 同样也分为两种:
    • 第一种:v-model,修饰符被加到modelModifiers中,形成this.modelModifiers={capitalize:true},然后子组件通过判断修饰符来进行响应操作;
    • 第二种:带参数v-model:title,修饰符使用类似,modelValue变为titlemodelModifiers名称变为titleModifiers
//默认情况下
<my-component v-model.capitalize="myText"></my-component>
//默认情况下
app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})//自定义的修饰符以对象形式被填到这里,默认为{}
    }
  },
  emits: ['update:modelValue'],
  methods: {
    emitValue(e) {
      let value = e.target.value
      if (this.modelModifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      this.$emit('update:modelValue', value)
    }
  },
  template: `<input
    type="text"
    :value="modelValue"
    @input="emitValue">`
})

Provide / Inject 详情

vue@2、vue@3都有

  • 父组件提供,内部所有子孙组件都可以接收;
  • Provide提供时有三种情况:对于传递普通字符串;对于传递组件内部数据;对于需要在子组件中传递可响应数据;

Provide提供:

app.component('todo-list', {
  data() {
    return {
      todos: ['Feed a cat', 'Buy tickets']
    }
  },
  ------提供普通数据
  provide: {
    user: 'John Doe'
  },
  -----提供组件内部数据,后续子组件中不会从变化自动更新
  provide() {
    return {
      todoLength: this.todos.length
    }
  },
  ------会响应到子组件中
  provide() {
    return {
      todoLength: Vue.computed(() => this.todos.length)
    }
  }
  template: `
    <div>
      {{ todos.length }}
      <!-- 模板的其余部分 -->
    </div>
  `
})

Inject接收:

app.component('todo-list-statistics', {
  inject: ['user'],
  created() {
    console.log(`Injected property: ${this.user}`) // > 注入 property: John Doe
  }
})

关于过渡、动画中的硬件加速

诸如 perspective、backface-visibility 和 transform:translateZ(x) 等 property 将让浏览器知道你需要硬件加速。

//样式中使用一个即可
perspective: 1000px;
backface-visibility: hidden;
transform: translateZ(0);

自定义指令

1、全局注册指令

  • vue@2:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})
  • vue@3:const app = Vue.createApp({})
// 注册一个全局自定义指令 `v-focus`
app.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  mounted(el) {
    // Focus the element
    el.focus()
  }
})

2、局部注册指令

  • vue@2:
directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}
  • vue@3:
directives: {
  focus: {
    // 指令的定义
    mounted(el) {
      el.focus()
    }
  }
}

3、钩子函数

vue@2vue@3说明
bindbeforeMount当指令第一次绑定到元素并且在挂载父组件之前调用
insertedmounted在挂载绑定元素的父组件时调用。
update所在组件的 VNode 更新时调用
beforeUpdate在更新包含组件的 VNode 之前调用
componentUpdatedupdated指令所在组件的 VNode 及其子 VNode 全部更新后调用。
beforeUnmount在卸载绑定元素的父组件之前调用
unbindunmounted只调用一次,指令与元素解绑时调用

4、具体参数

el、binding(略有不同)、vnode、oldVnode

5、函数简写
vue@2:默认是触发bind、update

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

vue@3:默认是触发mounted 和 updated

app.directive('pin', (el, binding) => {
  el.style.position = 'fixed'
  const s = binding.arg || 'top'
  el.style[s] = binding.value + 'px'
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值