# Vue3相比Vue2使用差异

# 挂载应用及注册全局API

// 2.0
import Vue from 'vue'
// 全局混入
Vue.minxin()
// 注册全局指令
Vue.directive('focus', {})
// 注册全局组件
Vue.component('my-component-name', { /* ... */ })
// 注册插件
Vue.use()
//绑定的全局方法和变量
Vue.prototype.xxx = xxx
// 挂载
new Vue({
    router,
    render:(h)=> h(App)
}).$mount(root)

// 3.0
import Vue from 'vue'
const app = Vue.createApp({})
// 混
app.mixin()
// 注册全局组件
app.component('SearchInput', SearchInputComponent)
// 注册全局指令
app.directive('focus', FocusDirective)
// 注册插件
app.use(LocalePlugin)
// 添加全局属性
app.config.globalProperties.$message = message 

3.0 将通过 Vue.createApp({}) 创建一个应用实例,在这个实例上面注册一些全局API

由于Vue3中全局API都会通过 app.xxx 的方法调用,所以之前通过 Vue.prototype.xxx 绑定的全局方法和变量将无法使用,可以采用如下方式来代替:

app.config.globalProperties.http = function(){}

# 组件生命周期

3.0 不再有 beforeDestroydestroyed 两个钩子,多了 beforeUnmountunmounted 两个勾子

# 组件上绑定事件

2.0 组件上绑定事件的特点:

  • 绑定原生事件,需要添加 .native 修辞符

  • 当组件内根元素有绑定同名事件时,只会触发组件内的事件,不会触发组件外事件,此时可以通过手动调用 this.$listeners[事件名]() 来绑定在组件上的事件

  • 具有 $listeners 属性,包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器

3.0 组件上绑定事件的特点:

  • 无需添加 .native 修辞符

  • 当组件内根元素有绑定同名事件时都会触发事件,先执行组件内的事件,再执行组件外的事件

  • 添加了 emits 属性,用法同 props,针对事件的,如果在emits 声明了事件,那么不会自动触发组件外的事件

  • 取消了 $listeners 属性, $attrs 中将包括组件 propsemits中未包含的所有属性和方法,如果 属性和事件出现同名的话,会合并在数组中(事件名没默认添加 on前缀,所以添加:onClick属性和@click 事件,这样才算重名)

    如果向上所说有 添加与事件同名的属性,在触发事件时,vue 也会误把这个属性当前函数执行,会报错的,即使读取那个作为属性的值,也将变成数组

# 使用非props属性的注意点

在组件定义的属性如果没有 props 定义,会直接赋值在根元素上,并存在以下特点

  1. 如果在组件上定义的属性和组件内的根元素定义了相同的属性,那么会采用组件上的属性

  2. <HelloWorld v-bind="{ttt: 'abc'}" ttt="lanjz" /> 这种即定义了属性的同时用使用 v-bind 包含相同属性,采用定义的属性,即lanjz

关于上面的第一点,3.0和2.0 使用的又有点区别

  • 2.0 虽然优先也是使用了组件上的属性,但是组件内如果有对属性进行动态修改,那么这个属性将变成修改的值

  • 而 3.0 中组件内如果有对属性进行动态修改,这个属性仍然还是组件外定义的属性

# v-model

3.0中 v-model 增加了自定义指令

<my-component v-model.capitalize="bar"></my-component>
app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  template: `
    <input type="text" 
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)">
  `,
  created() {
    console.log(this.modelModifiers) // { capitalize: true }
  }
})

# provide/inject

基本用法一致,但是如果希望 inject 中的值是响应的,那么处理方法是不同的

2.0 实现响应的条件有两点:

  1. provide 选项应该是返回一个对象的函数

  2. 传入的值是一个可监听的对象

  provide(){
    return {
      foo: this.item
    }
  },
  data(){
    return {
      item: {
        name: 'f'
      }
    }
  },

3.0 实现 provide 属性的响应的还可以通过 组合式 API 的形式

// todo

# 异步组件

//2.0
export default {
  name: "index",
  components: {
    Comp: import('./comp.vue')
  },
}
//3.0
import { defineAsyncComponent, computed } from 'vue'
export default {
  name: "index",
  components: {
    Comp: defineAsyncComponent(() => import('./comp.vue'))
  },
}

# 自定义指定

3.0 指定的钩子名称跟2.0 不一样了

# v-model

2.0 v-model 默认会利用名为 value 的 prop 和 input 作为事件

3.0 默认情况下,组件上的 v-model 使用 modelValue 作为 propupdate:modelValue 作为事件