Vue3.0

1、前言

Vue3 目前还是 Beta 版本,我们可以通过多种不同的方式来使用 Vue3

注意因为是 Beta 的原因,虽然主要的一些 API 基本是稳定的,但是这里涉及到的一些使用方式或许会在以后有变更
同时当前的一些生态也还没有完全完全完善,所以不要在生产环境中使用,即使作为学习,也应该随时关注官方的变化。

  • vue-next-webpack-preview
  • Vue Composition API插件
  • vue-cli-plugin-vue-next

2、vue-next-webpack-preview

https://github.com/vuejs/vue-next-webpack-preview

这种方式是使用 webpack 独立配置构建 Vue3 项目。

因为只是配置了基本特性(如单文件组件支持等),也没有构建上的优化,推荐作为学习使用。

3、Vue Composition API 插件

https://github.com/vuejs/composition-api

首先,Vue Composition API 只是 Vue3 中的其中一项特性(重要),该插件可以让我们在 Vue2 中只使用 Vue Composition API ,而不需要升级所有特性。

在vue2中安装使用

npm install @vue/composition-api
# or
yarn add @vue/composition-api
import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)
// use the APIs
import { ref, reactive } from '@vue/composition-api'

4、vue-cli-plugin-vue-next

https://github.com/vuejs/vue-cli-plugin-vue-next

一个把 Vue2 项目升级为 Vue3 的工具。

功能并不完善。

4-1、步骤

  1. 首先使用 vue-cli 工具构建一个 Vue2 的项目
  2. 在项目根目录下使用命令:vue add vue-next 构建成基于 Vue3 的项目。

在这里插入图片描述

5、new Vue() 与 createApp()

Vue3 之前使用 new Vue() 来构建应用根组件,现在改为 createApp() ,调用 $mount 方法进行挂载。

let app = new Vue() => let app = createApp(App);

Vue3 之前使用 Vue.use() 注册api,现在是挂到具体实例对象上

Vue.use => 实例对象.use()

6、Fragment

  • 之前的每一个独立的组件有且仅有一个顶层节点(元素),许多时候,我们不得不去为组件添加一层没有太多意义的顶层结构。
  • 现在 Vue3 支持了一个 Fragment 的特性,当组件中的顶层节点不是一个的时候,会通过 Fragment 来进行处理。

参考:DocumentFragment

在这里插入图片描述
运行没问题

7、Composition API(重点)

组合式 API 征求意见稿

API 手册

optionsAPI 选项式API

  1. vue通过选项(参数)的方式,对外提供了一组用于构建或使用它的 api,选项式编程,这就叫optionsAPI
  2. 选项式API 根据类型来组织数据(结构)
Vue.component({
  name: "HelloWorld",
  props: {
    msg: String
  }
});

Composition API 组合式API

  1. 根据功能组织代码
  2. 不同功能进行分类

setup

setup 函数是一个新的组件选项。作为在组件内使用 Composition API 的入口点。

  • 调用时机
    创建组件实例,然后初始化 props ,紧接着就调用setup 函数。从生命周期钩子的视角来看,它会在 beforeCreate 钩子之前被调用

  • 原来视图中可使用的数据来源很多:
    data,props,computed,methods,inject
    这种做法数据来源太多,容易造成混乱

  • vue3 视图中要使用的数据必须通过setup函数返回

    setup() {
        console.log("setup");
        
        let title = "lc"
        const changeTitle = () => {
            title = "hello vue";
            console.log(title);
            
        }
        return {
            title,
            changeTitle
        }
    }

但是这样写的数据并不是响应式的

响应式数据

ref

        // 把普通值变为一个可代理对象
        let title = ref("lc")
        console.log(title);

在这里插入图片描述
数据修改

        const changeTitle = () => {
            title.value = "hello vue";
            console.log(title);
        }

reactive

import { ref, reactive } from "vue";

export default {
    name: "Register",

    setup() {
        let formData = reactive({
            username: "",
            password: "",
            repassword: ""
        });
        console.log(formData);

        const submitRegister = () => {
            console.log("发送登录请求", formData);
        };
        return {
            formData,
            submitRegister
        };
    }
};

computed

        let errorMessage = computed(() => {
            return "abc"
        })
        let errorMessage = computed(() => {
            if (
                formData.username.trim() === "" ||
                formData.password.trim() === "" ||
                formData.repassword.trim() === ""
            ) {
                return "注册信息不符合要求";
            } else {
                return "可以提交"
                console.log("发送登录请求", formData);
            }
        });

watchEffect

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

watch

  • watch API 完全等效于 2.x this.$watch (以及 watch 中相应的选项)。
  • watch 需要侦听特定的数据源,并在回调函数中执行副作用。
  • 默认情况是懒执行的,也就是说仅在侦听的源变更时才执行回调。

对比 watchEffect,watch 允许我们:

  • 懒执行副作用;
  • 更明确哪些状态的改变会触发侦听器重新运行副作用;
  • 访问侦听状态变化前后的值。

复用数据逻辑

把可复用的数据放到一个文件下

import { ref, reactive, computed } from "vue";

let type = ref("register");

let formData = reactive({
    username: "",
    password: "",
    repassword: ""
});

let errorMessage = computed(() => {

    if (
        formData.username.trim() === "" ||
        formData.password.trim() === "" ||
        (
            type.value === "register" &&
            formData.repassword.trim() === ""
        )
    ) {
        return "注册信息不符合要求";
    } else {
        return "可以提交";
        console.log("发送登录请求", formData);
    }
});
const useSubmitRegister = () => {
    console.log("注册", formData);
};
const useSubmitLogin = () => {
    console.log("登录", formData);
};

export {
    type,
    formData,
    errorMessage,
    useSubmitRegister
};

生命周期钩子函数

可以通过on格式 onXXX直接导入函数来注册生命周期钩子:

import { onMounted, onUpdated, onUnmounted } from 'vue'

const MyComponent = {
  setup() {
    onMounted(() => {
      console.log('mounted!')
    })
    onUpdated(() => {
      console.log('updated!')
    })
    onUnmounted(() => {
      console.log('unmounted!')
    })
  },
}

这些生命周期钩子注册函数只能在 setup() 期间同步使用, 因为它们依赖于内部的全局状态来定位当前组件实例(正在调用 setup() 的组件实例), 不在当前组件下调用这些函数会抛出一个错误。

组件实例上下文也是在生命周期钩子同步执行期间设置的,因此,在卸载组件时,在生命周期钩子内部同步创建的侦听器和计算状态也将自动删除。

新增调试钩子函数

新增的钩子函数

除了和 2.x 生命周期等效项之外,组合式 API 还提供了以下调试钩子函数:

  • onRenderTracked
  • onRenderTriggered

两个钩子函数都接收一个 DebuggerEvent,与 watchEffect 参数选项中的 onTrack 和 onTrigger 类似:

export default {
  onRenderTriggered(e) {
    debugger
    // 检查哪个依赖性导致组件重新渲染
  },
}

setup 参数

  • 使用setup也需要通过options来定义props,通过第一个参数获取
  • 第二个参数为上下文对象,里面存入了非props参数$attrs,提交事件的方法emit
props: {
    msg: String
},

setup(props, context) {
    console.log("props", props);
    console.log("context", context);
}

在这里插入图片描述
在这里插入图片描述

访问组件对象

import { getCurrentInstance } from "vue";
export default {
    name: "HelloWorld",
    props: {
        msg: String
    },

    setup() {
        let instance = getCurrentInstance();
        console.log(instance);
    }
};

在这里插入图片描述

8、Teleport 传送门

https://github.com/vuejs/rfcs/pull/112

Vue3 新增的内置组件 <teleport>,又来解决如下的一个需求:

有时,组件模板的一部分在逻辑上属于这个组件,而从技术的角度来看(即:样式需求),最好将模板的这一部分移到 DOM 中的其他位置。

<div id="app">
  <h1>Move the #content with the portal component</h1>
  <teleport to="#endofbody">
    <div id="content">
      <p>
        this will be moved to #endofbody.<br />
        Pretend that it's a modal
      </p>
      <Child />
    </div>
  </teleport>
</div>
<div id="endofbody"></div>
...
components: {
  Child: { template: "<div>Placeholder</div>" }
},
...

9、Suspense

https://github.com/vuejs/rfcs/pull/148

异步组件

这里的异步组件工厂函数也可以返回一个如下格式的对象:

const AsyncComponent = () => ({
  // 需要加载的组件 (应该是一个 `Promise` 对象)
  component: import('./MyComponent.vue'),
  // 异步组件加载时使用的组件
  loading: LoadingComponent,
  // 加载失败时使用的组件
  error: ErrorComponent,
  // 展示加载时组件的延时时间。默认值是 200 (毫秒)
  delay: 200,
  // 如果提供了超时时间且组件加载也超时了,
  // 则使用加载失败时使用的组件。默认值是:`Infinity`
  timeout: 3000
})

10、一些杂项

10-1、v-model

https://github.com/vuejs/rfcs/pull/140

10-2、filters

https://github.com/vuejs/rfcs/pull/97

10-3、Custom Directive API Change

https://github.com/vuejs/rfcs/pull/32

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值