初学vue3

vue3抛弃了Flow类型注释,使用TypeScript重写了代码,增加了Composition API基于函数的API,解决了Vue2Options API不好拆分和重用的的问题.Vue3中使用Proxy重写了响应式原理,并且对编译器做了优化,重写了虚拟DOM,从而让渲染和update的性能都有了大幅度的提升.Vue3中移除了一些不常用的API,如filter.对Tree-shaking的支持更好,过滤掉未使用的模块使打包的体积更小.

官方文档

创建项目

  • 通过CDN <script src="https://unpkg.com/vue@next"></script>
  • 通过Vue-cli脚手架创建项目 注:需要将@vue/cli更新至4.5.0及以上 npm update -g @vue/cli
    vue create <project-name> 选择 vue3 的模板进行创建`

    1
    2
    3
    4
    5
    /*
    1. vue create <project-name> 选择vue3的模板进行创建
    2. cd <project-name>
    3. npm run serve
    */
  • 通过vite脚手架创建项目 注:Vite需要Node.js版本>=12.0.0
    npm init vite-app <project-name> 或 yarn create vite-app <project-name>

    1
    2
    3
    4
    5
    6
    /*
    1. npm init vite-app <project-name> 或 yarn create vite-app <project-name>
    2. cd helloVite
    3. npm install
    4. npm run dev
    */

全局API-createApp

1
2
3
4
5
6
// 入口文件 main.js
// vue3提供大量函数式API,推崇的是函数式编程
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App); // 使用createApp函数创建vue应用实例
app.mount("#app"); // 将组件App挂载到id为app的节点上

Vue3 主要更新

  1. Performance 重写了虚拟 DOM 的实现(跳过静态节点,只处理动态节点),update 性能提供,SSR 速度提高
  2. Tree shaking 全局和内部 API 已经被重构为支持 tree-shake,可以将无用模块过滤,仅打包需要和用到的部分
  3. Fragment (空文档标签)不再限于模板中的单个根节点,Vue3 的 template 支持多个根标签,Vue2 只能由一个根标签
  4. TypeScript 更好的 TypeScript 支持
  5. Custom Renderer API 自定义渲染器 将某些部分以 canvas 画布形式展示出来而不是 Dom 方式
  6. Composition API 组合式 API

    组合式API,替换原有的Options API,将逻辑相关的代码组织在一起,提高可读性和可维护性,更好的重用逻辑代码(避免mixins混入时命名冲突的问题),但是依然可以使用Options API

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // Options API
    export default {
    data () {
    return {}
    },
    methods: {},
    cooputed () {},
    watch: {},
    filters: {}
    }
    // Composition API 所有操作聚合在 setUp 中
    export default {
    name: "AsyncTest",
    async setup() {
    let { id, name } = {id: 1, name: 'tew'};
    return {
    id,
    name,
    };
    },
    };
  7. Proxy 数据劫持,Vue3 中的响应式原理是基于 ES6 的 Proxy 实现的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    /*
    Vue2是基于0bject.defineProperty实现数据劫持的(get/set)
    + 需要给对象中的每一个属性分别遍历做劫持「对于后期新增的属性是没有做劫持的,vue2中可以基于$set实现新增属性的劫持」
    + 对于数组中的每一项没有做劫持「vue2中重写了数组7个方法,后期通过这7个方法修改数组中的某一项,才会让视图重新渲染」
    + 默认劫持是"浅”的,vue2自动基于递归的方式实现了深度劫持
    + ES5的API,兼容IE9及以上
    Vue3中的响应式数据,是基于ES6中的Proxy实现的
    + ES6的API,不兼容IE
    + Proxy除了提供get/set监听之外,还提供了其他大量的监听函数
    + Proxy无需自己依次遍历对象的每个属性,只需要代理整个对象,则所有属性都被劫持,新增属性也会被劫持
    + Proxy直接对数组每一项做代理操作数组的某一项都会触发试图更新,无需重写数组的方法
    + Proxy默认也是只对对象的第一层做代理,也需要递归遍历实现深层次代理
    */
    // proxy 基本使用
    // const data = {
    // name: 'zhangsan',
    // age: 20,
    // }
    const data = ['a', 'b', 'c']
    const proxyData = new Proxy(data, {
    get(target, key) {
    return Reflect.get(target, key)
    },
    set(target, key, val) {
    // 重复的数据,不处理
    if (val === target[key]) return true
    Reflect.set(target, key, val)
    },
    deleteProperty(target, key) {
    Reflect.deleteProperty(target, key)
    }
    })
  8. Teleport 传送门

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    // index.html
    <body>
    <div id="#app"></div>
    <div id="#other"></div>
    </body>
    // demo.vue
    /*
    Teleport 把当前组件的部分内容抽离出来放到页面中 非#app的容器中 基于to指定放在那个容器下
    */
    <template>
    <h2>Hello Vue3!</h2>
    <Teleport to="#other">
    <span>hello world!</span>
    </Teleport>
    </template>
    // 渲染结果
    /*
    <body>
    <div id="app" data-v-app="">
    <h2>Hello Vue3!</h2>
    <!--teleport start-->
    <!--teleport end-->
    </div>
    <div id="other">
    <span>hello world!</span>
    </div>
    </body>
    */
  9. Suspense 可在嵌套层级中等待嵌套的异步依赖项

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    <!-- AsyncTest.vue -->
    <template>
    获取的用户信息是<br />
    用户编号: {{ id }}<br />
    用户姓名: {{ name }}<br />
    </template>
    <script>
    const query = () => {
    return new Promise((resolve, reject) => {
    setTimeout(() => {
    resolve({ id: 1, name: "tew" });
    }, 2000);
    });
    };
    export default {
    name: "AsyncTest",
    async setup() {
    let { id, name } = await query();
    return {
    id,
    name,
    };
    },
    };
    </script>
    <!-- App.vue -->
    <!--
    <template>
    <h2>Hello Vue3!</h2>
    <AsyncTest /> 直接使用异步组件无法使用 需要使用 Suspense
    </template>
    -->
    <template>
    <h2>Hello Vue3!</h2>
    <Suspense>
    <!-- 异步组件加载成功之后显示的内容 -->
    <template #default>
    <AsyncTest />
    </template>
    <!-- 异步组件加载成功之前显示的内容 -->
    <template #fallback>loading... </template>
    </Suspense>
    </template>
    <script>
    import AsyncTest from "./AsyncTest.vue";
    export default {
    name: "App",
    components: {
    AsyncTest,
    },
    };
    </script>
-------------本文结束感谢您的阅读-------------
0%