带你体验Vue2和Vue3开发组件有什么区别

https://v3.cn.vuejs.org/guide/migration/introduction.html

创建应用实例的方法

<div id="app"> {{ message }} </div>

Vue2 中使用 new Vue(…).$mount(…)
data 可以是对象 也可以是 函数返回对象

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

或者 手动挂载

var app = new Vue({
    data() {
        return {
            message: 'Hello Vue!'
        }
    }
}).$mount('#app')

Vue3 中 使用 Vue.createApp(…).mount(…)
data 必须是一个函数返回对象

var vm = Vue.createApp({
  data() {
    return {
        message: 'Hello Vue!'
    }
  }
}).mount('#app')

Vue 全局 API 修改

https://v3.cn.vuejs.org/guide/migration/global-api.html

2.x 全局 API3.x 实例 API (app)
Vue.configapp.config
Vue.config.productionTipremoved
Vue.config.ignoredElementsapp.config.compilerOptions.isCustomElement
Vue.componentapp.component
Vue.directiveapp.directive
Vue.mixinapp.mixin
Vue.useapp.use
Vue.prototypeapp.config.globalProperties
Vue.extendremoved

Vue2 中 在Vue类上直接注册 Vue.component(…)

// 定义名为 todo-item 的新组件
Vue.component('todo-item', {
  template: '<li>这是个待办项</li>'
})

var app = new Vue(...)

Vue3 中 在Vue实例上注册 app.component(…)

// 创建 Vue 应用
const app = Vue.createApp(...)

// 定义名为 todo-item 的新组件
app.component('todo-item', {
  template: `<li>这是个待办项</li>`
})

// 挂载 Vue 应用
app.mount(...)

Vue3 增加根组件概念 vm

createApp 返回应用的实例,而
mount 不返回应用本身,它返回的是根组件实例

原来 Vue2的时候,直接返回的便是根组件实例 vm,不存在 应用的实例 app 的概念

const app = Vue.createApp(...)
                .component('MyComponentName', {})
                .directive('focus', FocusDirective)
                .use(MyPlugin)
const vm = app.mount('#app')

生命周期

主要生命周期都是 创建、挂载、更新、销毁

Vue2:beforeCreated created beforeMounted mounted beforeUpdated updated beforeDestroyed destroyed
Vue3:beforeCreated created beforeMounted mounted beforeUpdated updated beforeUnmounted unmounted

destroyed 生命周期选项被重命名为 unmounted
beforeDestroy 生命周期选项被重命名为 beforeUnmount

生命周期示意图
https://v3.cn.vuejs.org/images/lifecycle.svg
https://cn.vuejs.org/images/lifecycle.png

不同钩子在不同阶段调用几乎是一致的,简单理解为只是改了一个阶段的钩子名称

Vue3组件可以有多个根元素

Vue2 中一个组件只能有一个根元素

<my-component class="baz"></my-component>
app.component('my-component', {
  template: `
    <p :class="$attrs.class">Hi!</p>
    <span>This is a child component</span>
  `
})

在Vue2中 组件上的 class 等属性,会直接传递给唯一的根元素,

在Vue3中,当组件上的根元素只有一个时,属性传递方式同Vue2一样,
但是有多个根元素时,可以使用 $attrs 组件属性将组件上的属性传递到某个根元素上

v-if 与 v-for 级别不同

Vue2 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
Vue3 当 v-if 与 v-for 一起使用时,v-if 具有比 v-for 更高的优先级。

注意:
不推荐同时使用 v-if 和 v-for。
不推荐同时使用 v-if 和 v-for。
不推荐同时使用 v-if 和 v-for。

<template> 中使用 v-for

Vue2 :key 不能放到 template 上

  <template v-for="item in items">
    <li :key="item">{{ item }}</li>
  </template>

Vue3 :key 可以放到 template 上

  <template v-for="item in items" :key="item">
    <li>{{ item }}</li>
  </template>

Vue3 组件新增 emits 选项

和 prop 类似,组件可触发的事件可以通过 emits 选项被定义
这个选项可以用来定义组件可以向其父组件触发的事件。
该选项也可以接收一个对象,该对象允许开发者定义传入事件参数的验证器,和 props 定义里的验证器类似。
强烈建议使用 emits 记录每个组件所触发的所有事件。
因为我们移除了 v-on.native 修饰符。任何未声明 emits 的事件监听器都会被算入组件的 $attrs 并绑定在组件的根节点上。
当在 emits 选项中定义了原生事件 (如 click) 时,将使用组件中的事件替代原生事件侦听器。

<template>
  <div>
    <p>{{ text }}</p>
    <button v-on:click="$emit('accepted')">OK</button>
  </div>
</template>
<script>
  export default {
    props: ['text'],
    emits: ['accepted']
  }
</script>

is 属性用于原生 HTML 元素

当它用于原生 HTML 元素时,is 的值必须以 vue: 开头,才可以被解释为 Vue 组件。这是避免和原生自定义元素混淆。

Vue2

<table>
  <tr is="blog-post-row"></tr>
</table>

Vue3

<table>
  <tr is="vue:blog-post-row"></tr>
</table>

组件禁用 Attribute 继承

如果你不希望组件的根元素继承 attribute,你可以在组件的选项中设置 inheritAttrs: false
$attrs property ,你可以手动决定这些 attribute 会被赋予哪个元素

Vue2
inheritAttrs: false 选项不会影响 style 和 class 的绑定。

Vue3
通过将 inheritAttrs 选项设置为 false,你可以访问组件的 $attrs property,该 property 包括组件 props 和 emits property 中未包含的所有属性 (例如,class、style、v-on 监听器等)。

Vue3 组件 v-model 自定义修饰符

在 2.x 中,我们对组件 v-model 上的 .trim 等修饰符提供了硬编码支持。
但是,如果组件可以支持自定义修饰符,则会更有用。
在 3.x 中,添加到组件 v-model 的修饰符将通过 modelModifiers prop 提供给组件

<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">`
})

对于带参数的 v-model 绑定,生成的 prop 名称将为 arg + “Modifiers”:

<my-component v-model:description.capitalize="myText"></my-component>
app.component('my-component', {
  props: ['description', 'descriptionModifiers'],
  emits: ['update:description'],
  template: `
    <input type="text"
      :value="description"
      @input="$emit('update:description', $event.target.value)">
  `,
  created() {
    console.log(this.descriptionModifiers) // { capitalize: true }
  }
})

Vue3 组合式 API

将同一个逻辑关注点相关代码收集在一起

在 Vue 2 中,mixin 是将部分组件逻辑抽象成可重用块的主要工具。但是,他们有几个问题:
Mixin 很容易发生冲突:因为每个 mixin 的 property 都被合并到同一个组件中,所以为了避免 property 名冲突,你仍然需要了解其他每个特性。
可重用性是有限的:我们不能向 mixin 传递任何参数来改变它的逻辑,这降低了它们在抽象逻辑方面的灵活性。
为了解决这些问题,我们添加了一种通过逻辑关注点组织代码的新方法:组合式 API。

具体使用方法查看文档
https://v3.cn.vuejs.org/guide/composition-api-introduction.html

Teleport

Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下渲染了 HTML,而不必求助于全局状态或将其拆分为两个组件。

使用 <<teleport to="body">> 告诉 Vue “Teleport 这个 HTML 插入到该‘body’标签”。

app.component('modal-button', {
  template: `
    <button @click="modalOpen = true">
        Open full screen modal! (With teleport!)
    </button>

    <teleport to="body">
      <div v-if="modalOpen" class="modal">
        <div>
          I'm a teleported modal! 
          (My parent is "body")
          <button @click="modalOpen = false">
            Close
          </button>
        </div>
      </div>
    </teleport>
  `,
  data() {
    return { 
      modalOpen: false
    }
  }
})

Vue3 watchEffect

它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。

首次运行 watchEffect 方法自动执行
当 count 值变化, watchEffect 方法再次自动执行,类似于计算属性,依赖项变化,重新计算

const count = ref(0)
watchEffect(() => console.log(count.value))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

了 义

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值