vue3学习大全(1)
阅读原文时间:2023年07月09日阅读:3

# vue3.0

Vue3.0 在北京时间2020年9月19 日凌晨,发布了 3.0 版本,代号:*One Piece*

1.新特性

Vue 3 中一些需要关注的新功能包括:

  • [组合式 API](https://v3.cn.vuejs.org/guide/composition-api-introduction.html)
  • [Teleport 将组件内容传递到父组件以外的任何区域](https://v3.cn.vuejs.org/guide/teleport.html)
  • [允许存在多个节点](https://v3.cn.vuejs.org/guide/migration/fragments.html)
  • [触发组件选项 可以驼峰传递事件 发送事件前需要声明 可以对事件进行验证](https://v3.cn.vuejs.org/guide/component-custom-events.html)
  • createRenderer可以跨平台渲染
  • 单文件组件组合式 API 语法糖


    ```

    ```html

    name: {{ name }}


    ```

    ```js
    const Counter = {
    data() {
    return {
    name: '李雷'
    }
    }
    }

    Vue.createApp(Counter).mount('#counter')
    ```

    到目前为止,我们依旧觉得,和我们原来的vue2是差别不大的,但其实已经有变化了,现在在vue3.0中,必须明确的声明`data属性必须是一个函数`,另外就是不在需要去实例化Vue这个操作了,而是引入了一3个叫做`createApp`的方法,创建了一个子实例

    5.过滤器

    从 Vue 3.0 开始,过滤器已移除,且不再支持。取而代之的是,我们建议用方法调用或计算属性来替换它们。

    6.组件

    5.1.组件的定义

    我们的一个vue3项目就已经跑起来啦,但是有一个感觉就是,就这? 多数人心中肯定有疑惑,就这??????和vue2的区别也不大嘛?的确,vue3本质上保留了vue2的编写特性,别着急,下面我们再来看看组件的定义

    ```html

    {{name}}


    ```

    发现不同了吗?现在在`vue3.0中已经开始支持多节点了`,再也不同担心vue2.0单节点烦人的警告️啦

    ```js
    let app = Vue.createApp({
    data() {
    return {
    name: "李雷"
    }
    },
    mounted() {
    console.log(this.a)
    console.log(this)
    }
    })
    app.component("test", {
    template: "#test",
    data() {
    return {
    msg: "子组件"
    }
    }
    })
    //注意这里的调用顺序
    app.mount("#app")
    ```

    好了 定义完了,这里要注意的一个问题就是`app.mount`这个方法一定要在`组件注册完毕之后`调用

    5.2.组件之间的传参

    • 父子传参

    • 子父传参

    发现一个问题就是,和原来的vue2.0也没啥区别,感觉学了个寂寞,还有一个问题就是,兄弟传参哪儿去了?

    bus总线

    很遗憾的一个问题就是在vue3中`$on`,`$off` 和 `$once` 实例方法已被移除,组件实例不再实现事件触发接口。

    处理方案可以被替换为使用外部的、实现了事件触发器接口的库,例如 [mitt](https://github.com/developit/mitt) 或 [tiny-emitter](https://github.com/scottcorgan/tiny-emitter)。

    ```js
    // eventBus.js
    import emitter from 'tiny-emitter/instance'

    export default {
    $on: (…args) => emitter.on(…args),
    $once: (…args) => emitter.once(…args),
    $off: (…args) => emitter.off(…args),
    $emit: (…args) => emitter.emit(…args),
    }
    ```

    5.3.异步组件

    5.4.1.传统HTML基本使用

    import(/*webpackChunkName:''*/'xxxx'')

    在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了实现这个效果,Vue 有一个 `defineAsyncComponent` 方法:

    ```js
    const { createApp, defineAsyncComponent } = Vue

    const app = createApp({})

    const AsyncComp = defineAsyncComponent(
    () =>
    new Promise((resolve, reject) => {
    resolve({
    template: '

    I am async!
    '
    })
    })
    )

    app.component('async-example', AsyncComp)
    ```

    2.使用模块化

    如你所见,此方法接受一个返回 `Promise` 的工厂函数。从服务器检索组件定义后,应调用 Promise 的 `resolve` 回调。你也可以调用 `reject(reason)`,来表示加载失败。

    你也可以在工厂函数中返回一个 `Promise`,把 webpack 2 及以上版本和 ES2015 语法相结合后,我们就可以这样使用动态地导入:

    ```js
    import { defineAsyncComponent } from 'vue'

    const AsyncComp = defineAsyncComponent(() =>
    import('./components/AsyncComponent.vue')
    )

    app.component('async-component', AsyncComp)
    ```

    当[在局部注册组件](https://v3.cn.vuejs.org/guide/component-registration.html#局部注册)时,你也可以使用 `defineAsyncComponent`:

    ```js
    import { createApp, defineAsyncComponent } from 'vue'

    createApp({
    // …
    components: {
    AsyncComponent: defineAsyncComponent(() =>
    import('./components/AsyncComponent.vue')
    )
    }
    })
    ```

    3.与 Suspense 一起使用

    异步组件在默认情况下是*可挂起*的。这意味着如果它在父链中有一个 ``,它将被视为该 `` 的异步依赖。在这种情况下,加载状态将由 `` 控制,组件自身的加载、错误、延迟和超时选项都将被忽略。

    通过在其选项中指定 `suspensible: false`,异步组件可以退出 `Suspense` 控制,并始终控制自己的加载状态。

    在正确渲染组件之前进行一些异步请求是很常见的事。组件通常会在本地处理这种逻辑,绝大多数情况下这是非常完美的做法。

    该 `` 组件提供了另一个方案,允许将等待过程提升到组件树中处理,而不是在单个组件中。

    一个常见的[异步组件](https://v3.cn.vuejs.org/guide/component-dynamic-async.html#异步组件)用例:

    ```vue


    ```

    `` 组件有两个插槽。它们都只接收一个直接子节点。`default` 插槽里的节点会尽可能展示出来。如果不能,则展示 `fallback` 插槽里的节点。

    7.使用vue-cli开启一个vue3项目

    1. 升级最新vue-cli

    升级到5

    ```bash
    npm i @vue/cli -g
    ```

    1. 创建一个项目

    ```bash
    vue create 项目
    ```

    3.兼容vue-cli3.0

    8.指令

    vue3的指令几乎和vue2.0保持是一致的,但是增加了以下新特性

    1.组件上可以绑定多个model了

    • `组件可以绑定多个model`
    • `v-model` prop 和事件默认名称已更改:
      • We can prop:`value` -> `modelValue`;
      • 事件:`input` -> `update:modelValue`
    • 可以自定义 `v-model` 修饰符

    v-model在元素上的写法没有变化,但是在组件中的写法有了新特性,写法就是在指令后面跟上指令参数,指令参数就是绑定的数据名称

    **下面是一个例子**

    ```html

    {{name}}

    {{name2}}



    ```

    对于所有不带参数的 `v-model`,请确保分别将 prop 和 event 命名更改为 `modelValue` 和 `update:modelValue`

    2.指令优先级的变化

    Vue.js 中使用最多的两个指令就是 `v-if` 和 `v-for`,因此开发者们可能会想要同时使用它们。虽然不建议这样做,但有时确实是必须的2.x 版本中在一个元素上同时使用 `v-if` 和 `v-for` 时,`v-for` 会优先作用。

    3.x 版本中 `v-if` 总是优先于 `v-for` 生效

    ```vue


    ```

    3.v-on.native修饰符

    `v-on` 的 `.native` 修饰符已被移除。

    • 2.x 语法

    默认情况下,传递给带有 `v-on` 的组件的事件监听器只能通过 `this.$emit` 触发。要将原生 DOM 监听器添加到子组件的根元素中,可以使用 `.native` 修饰符:

    ```html

    ```

    • 3.x 语法

    `v-on` 的 `.native` 修饰符已被移除。同时,[新增的 `emits` 选项](https://v3.cn.vuejs.org/guide/migration/emits-option.html)允许子组件定义真正会被触发的事件。

    因此,对于子组件中*未*被定义为组件触发的所有事件监听器,Vue 现在将把它们作为原生事件监听器添加到子组件的根元素中 (除非在子组件的选项中设置了 `inheritAttrs: false`)。

    ```html

    ```

    ```vue
    MyComponent.vue


    ```

    4.自定义指令

    自定义指令基本和vue2.0是保持一致的,但是有不同的地方就是,指令钩子函数增加到了7个,下面是一个基本用法

    ```js
    const app = Vue.createApp({})
    // 注册一个全局自定义指令 `v-focus`
    app.directive('focus', {
    // 当被绑定的元素挂载到 DOM 中时……
    mounted(el) {
    // 聚焦元素
    el.focus()
    }
    })
    ```

    局部注册的方式是在app中

    ```js
    directives: {
    focus: {
    // 指令的定义
    mounted(el) {
    el.focus()
    }
    }
    }
    ```

    不同的是vue3.0的指令钩子函数增加到了7个分别是

    • `created`:在绑定元素的 attribute 或事件监听器被应用之前调用
    • `beforeMount`:当指令第一次绑定到元素并且在挂载父组件之前调用。
    • `mounted`:在绑定元素的父组件被挂载后调用。
    • `beforeUpdate`:在更新包含组件的 VNode 之前调用。

    提示

    • `updated`:在包含组件的 VNode **及其子组件的 VNode** 更新后调用。
    • `beforeUnmount`:在卸载绑定元素的父组件之前调用
    • `unmounted`:当指令与元素解除绑定且父组件已卸载时,只调用一次。

    7.小结

    1. `vue3.0中已经开始支持多节点了`
    2. 在vue3中`data属性必须是一个函数`
    3. `vue3里面有app的概念,可以防止染全局配置`
    4. `属性的劫持,使用了proxy`
    5. `移除了过滤器`
    6. `移除了eventBus`
    7. `vue3.0中组件上可以绑定多个v-model了 而且参数和事件有变化`
    8. `在vue3.0中 v-if的优先级要高于v-for`
    9. `vue3.0中移除了native修饰符`

    9.使用构建工具vite

    [Vite](https://cn.vitejs.dev/) 是一个 web 开发构建工具,由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动。

    通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目。

    使用 npm:

    ```bash

    npm 6.x

    $ npm init vite@latest --template vue

    npm 7+,需要加上额外的双短横线

    $ npm init vite@latest -- --template vue

    $ cd
    $ npm install
    $ npm run dev
    ```

    或者 yarn:

    ```bash
    $ yarn create vite --template vue
    $ cd
    $ yarn
    $ yarn dev
    ```

    模块化样式

    1.选择器支持插槽了

    在单文件组件范围的样式中提供更一致的自定义CSS扩展。

    ```html


    ```

    2.深度选择器的改进

    • `>>>` 和/deep/` 支持被弃用

    • `::v-deep` 组合被弃用:

      ```css
      /* qiyong */
      ::v-deep .bar {}
      ```

      使用这种方式来替代上面的写法

      ```css
      ::v-deep(.bar) {}
      ```

      上述将编译为

      ```css
      [v-data-xxxxxxx] .bar {}
      ```

    ref

    在 Vue 2 中,在 `v-for` 中使用的 `ref` attribute 会用 ref 数组填充相应的 `$refs` property。当存在嵌套的 `v-for` 时,这种行为会变得不明确且效率低下。

    在 Vue 3 中,此类用法将不再自动创建 `$ref` 数组。要从单个绑定获取多个 ref,请将 `ref` 绑定到一个更灵活的函数上 (这是一个新特性):

    ```html


    ```

    结合选项式 API:

    ```333 js
    export default {
    data() {
    return {
    itemRefs: []
    }
    },
    methods: {
    setItemRef(el) {
    if (el) {
    this.itemRefs.push(el)
    }
    }
    },
    beforeUpdate() {
    this.itemRefs = []
    },
    updated() {
    console.log(this.itemRefs)
    }
    }
    ```

    结合组合式 API:

    ```js
    import { onBeforeUpdate, onUpdated } from 'vue'

    export default {
    setup() {
    let itemRefs = []
    const setItemRef = el => {
    if (el) {
    itemRefs.push(el)
    }
    }
    onBeforeUpdate(() => {
    itemRefs = []
    })
    onUpdated(() => {
    console.log(itemRefs)
    })
    return {
    setItemRef
    }
    }
    }
    ```

    注意:

    • `itemRefs` 不必是数组:它也可以是一个对象,其 ref 可以通过迭代的 key 被设置。
    • 如有需要,`itemRef` 也可以是响应式的,且可以被侦听。

    emits选项**新增**

    概述

    Vue 3 现在提供一个 `emits` 选项,和现有的 `props` 选项类似。这个选项可以用来定义一个组件可以向其父组件触发的事件。

    2.x 的行为

    在 Vue 2 中,你可以定义一个组件可接收的 prop,但是你无法声明它可以触发哪些事件:

    ```vue


    ```

    3.x 的行为

    和 prop 类似,现在可以通过 `emits` 选项来定义组件可触发的事件:

    ```vue


    ```

    该选项也可以接收一个对象,该对象允许开发者定义传入事件参数的验证器,和 `props` 定义里的验证器类似。

    迁移策略

    强烈建议使用 `emits` 记录每个组件所触发的所有事件。

    这尤为重要,因为我们[移除了 `.native` 修饰符](https://v3.cn.vuejs.org/guide/migration/v-on-native-modifier-removed.html)。任何未在 `emits` 中声明的事件监听器都会被算入组件的 `$attrs`,并将默认绑定到组件的根节点上。

    [#](https://v3.cn.vuejs.org/guide/migration/emits-option.html#示例)示例

    对于向其父组件透传原生事件的组件来说,这会导致有两个事件被触发:

    ```vue


    ```

    当一个父级组件拥有 `click` 事件的监听器时:

    ```html

    ```

    该事件现在会被触发*两次*:

    • 一次来自 `$emit()`。
    • 另一次来自应用在根元素上的原生事件监听器。

    现在你有两个选项:

    1. 正确地声明 `click` 事件。当你真的在 `` 的事件处理器上加入了一些逻辑时,这会很有用。
    2. 移除透传的事件,因为现在父组件可以很容易地监听原生事件,而不需要添加 `.native`。适用于你只想透传这个事件。

    emit验证

    Emit也可以像props那样进行验证了

    ```vue
    const app = createApp({})

    // 数组语法
    app.component('todo-item', {
    emits: ['check'],
    created() {
    this.$emit('check')
    }
    })

    // 对象语法
    app.component('reply-form', {
    emits: {
    // 没有验证函数
    click: null,

    // 带有验证函数  
    submit: payload => {  
      if (payload.email && payload.password) {  
        return true  
      } else {  
        console.warn(\`Invalid submit event payload!\`)  
        return false  
      }  
    }  

    }
    })
    ```