除了composition API,vue3.0文档又带来了什么新东西?

异步组件

在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。

2.0中 我们这么用⬇️

const asyncPage = () => import('./NextPage.vue') //return a promise

const asyncPage = {
  component: () => import('./NextPage.vue'),
  delay: 200,
  timeout: 3000,
  error: ErrorComponent,
  loading: LoadingComponent
}

3.0用法(由于组件被定义为纯函数,我们需要引入defineAsyncComponent实现异步)

import { defineAsyncComponent } from 'vue'
import ErrorComponent from './components/ErrorComponent.vue'
import LoadingComponent from './components/LoadingComponent.vue'

// Async component without options
const asyncPage = defineAsyncComponent(() => import('./NextPage.vue'))

// Async component with options
const asyncPageWithOptions = defineAsyncComponent({
  loader: () => import('./NextPage.vue'),
  delay: 200,
  timeout: 3000,
  errorComponent: ErrorComponent,
  loadingComponent: LoadingComponent
})

自定义指令

2.0中 我们这么用⬇️

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

钩子函数:

3.0用法(添加了更加丰富的生命周期钩子函数)

const MyDirective = {
  beforeMount(el, binding, vnode, prevVnode) {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  beforeUnmount() {}, // new
  unmounted() {}
}

const app = Vue.createApp({})

app.directive('highlight', {
  beforeMount(el, binding, vnode) {
    el.style.background = binding.value
  }
})

自定义元素互操作更改(破坏性改变)

2.0中 我们这么用⬇️

1. ignoredElements

Vue.config.ignoredElements = [
  'my-custom-web-component',
  'another-web-component',
  // 用一个 `RegExp` 忽略所有“ion-”开头的元素
  // 仅在 2.5+ 支持
  /^ion-/
]

使 Vue 忽略在 Vue 之外的自定义元素 (e.g. 使用了 Web Components APIs)。否则,它会假设你忘记注册全局组件或者拼错了组件名称,从而抛出一个关于 Unknown custom element 的警告。

举例: 假如我使用了未定义的<icon></icon>组件

报错:(这个检查在vue3.0中在编译时就会进行,而2.0是在运行时进行的)

使用场景:有时候我们会再引入其他第三方库的组件,但是vue会抛出错误,我们要避免这个错误,可以在Vue.config.ignoredElements配置里面配置下。

3.0用法

// in webpack config
rules: [
  {
    test: /\.vue$/,
    use: 'vue-loader',
    options: {
      compilerOptions: {
        isCustomElement: tag => tag === 'plastic-button'
      }
    }
  }
  // ...
]

改变原因:自定义ignoredElements现在在模板编译期间执行,应通过编译器选项(而不是运行时配置)进行配置。

2.is属性的使用

2.0中 我们这么用⬇️

<button is="plastic">Click Me!</button>

它被解释为使用name渲染Vue组件plastic,等同于:

<plastic> Click Me!</plastic>

或者

<component v-bind:is="currentTabComponent" class="tab"></component>

这里的用法是动态组件渲染 不了解is具体使用的看这里:用于动态组件且基于 DOM 内模板的限制来工作。

在3.0中,仅将Vue对 is prop 的特殊处理限制在标签上。

<component v-bind:is="currentTabComponent"></component>

也即是说在上面button标签例子中的is在vue3.0只会呈现一个普通prop的效果

3.is进行In-DOM模板解析的变通办法

这个不太常见,只在HTML中使用vue会出现这个问题,.vue文件没有这个情况

2.0中 我们这么用⬇️

 <ul>
  <li></li>
  <li></li>
  <li></li>
</ul>

总所周知,ul里面嵌套li的写法是html语法的固定写法(还有如table,select等)

<ul>
  <my-component></my-component>
  <my-component></my-component>
</ul>

my-component是我们自己写的组件,但是html在渲染dom的时候,my-component对ul来说并不是有效的dom,甚至会报错。

解决方法:

<ul>
  <li is='my-component'></li>
</ul>

在3.0中

<ul>
  <li v-is='"my-component"'></li>
</ul>

用v-is取代了is,在写法上和上面一种is的功能也区分开了

data定义(破坏性改变)

2.0中 我们这么用⬇️

<!-- Object Declaration -->
<script>
  const app = new Vue({
    data: {
      apiKey: 'a1b2c3'
    }
  })
</script>

<!-- Function Declaration -->
<script>
  const app = new Vue({
    data() {
      return {
        apiKey: 'a1b2c3'
      }
    }
  })
</script>

Data支持两种格式(Function/Object)的定义

vue3.0中只支持Function这一种定义方法

Fragment

2.0中 我们这么用⬇️

<!-- Layout.vue -->
<template>
  <div>
    <header>...</header>
    <main>...</main>
    <footer>...</footer>
  </div>
</template>

如果不加这个<div>就会报下面这个错: Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead

3.0中支持不止一个根标签:

<!-- Layout.vue -->
<template>
  <header>...</header>
  <main v-bind="$attrs">...</main>
  <footer>...</footer>
</template>

渲染API

2.0中 我们这么用⬇️

export default {
  render(h) {
    return h('div')
  }
}

3.0中h 函数现在已全局导入,而不是传递给渲染函数作为参数 import { h } from 'vue'

export default {
  render() {
    return h('div')
  }
}

v-model

2.0中 我们这么用⬇️

<ChildComponent v-model="pageTitle" />

<!-- 上下等效 -->

<ChildComponent :value="pageTitle" @input="pageTitle = $event" />

3.0中变化为这样:

<ChildComponent v-model="pageTitle" />

<!-- 上下等效 -->

<MyBook :modelValue="pageTitle" @update:modelValue="pageTitle = $event" />

1.一个组件支持多个v-model

<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />


<ChildComponent
  :title="pageTitle"
  @update:title="pageTitle = $event"
  :content="pageContent"
  @update:content="pageContent = $event"
/>

2.v-model自定义修饰符

类似于2.0的.tirm修饰符

例子:

<div id="app">
  <my-component v-model.capitalize="myText"></my-component>
  {{ myText }}
</div>

const app = Vue.createApp({
  data() {
    return {
      myText: ''
    }
  }
})

app.component('my-component', {
  props: {
    modelValue: String,
    modelModifiers: {
      default: () => ({})
    }
  },
  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"
    v-bind:value="modelValue"
    v-on:input="emitValue">`
})

app.mount('#app')

Vue实例

2.0中 我们这么用⬇️

Vue.component('button-counter', {
  data: () => ({
    count: 0
  }),
  template: '<button @click="count++">Clicked {{ count }} times.</button>'
})

Similarly, this is how a global directive is declared:
Vue.directive('focus', {
  inserted: el => el.focus()
})

从技术上讲,Vue 2没有app的概念。我们定义为app的只是通过创建的根Vue实例new Vue()从同一个Vue构造函数创建的每个根实例都共享相同的全局配置。用起来很方便,但结果是不可避免的造成了全局污染,并且全局配置使测试过程中意外污染其他测试案例变得容易。

vue3.0:

调用createApp返回一个新的vue实例,这是Vue 3中的一个新概念,每个实例拥有了自己的配置项。

import { createApp } from 'vue'

const app = createApp()

1.挂载app实例

import { createApp } from 'vue'
import MyApp from './MyApp.vue'

const app = createApp(MyApp)
app.mount('#app')

const app = createApp(MyApp)

app.component('button-counter', {
  data: () => ({
    count: 0
  }),
  template: '<button @click="count++">Clicked {{ count }} times.</button>'
})

app.directive('focus', {
  mounted: el => el.focus()
})

app.mount('#app')

2.在app之间共享配置

import { createApp } from 'vue'
import Foo from './Foo.vue'
import Bar from './Bar.vue'

const createMyApp = (VueInstance) => {
  const app = createApp(VueInstance)
  app.directive('focus' /* ... */)

  return app
}

createMyApp(Foo).mount('#foo')
createMyApp(Bar).mount('#bar')

现在,该focus指令将在Foo和Bar实例及其后代中可用。

相关参考文档:v3.vuejs.org/

原文链接:juejin.im

上一篇:【我上我也行】前端自动化部署Jenkins最佳实践
下一篇:搭建一个基于react+TS+antd的组件库(2)

相关推荐

  • 高阶组件 + New Context API = ?

    1. 前言 继上次小试牛刀尝到高价组件的甜头之后,现已深陷其中无法自拔。。。那么这次又会带来什么呢?今天,我们就来看看【高阶组件】和【New Context API】能擦出什么火花! 2. New C...

    2 年前
  • 面试!你真的准备好了吗?|手写API系列梳理

    "不畏惧,不讲究,未来的日子好好努力"——大家好!我是小芝麻😄 标题党,它又、又、又来了...... 这篇文章是集合了小芝麻之前所有写过和没写过的API的汇总,为后面整体复习做准备,如果...

    3 个月前
  • 重构 - 设计API的扩展机制

    1.前言 上篇文章,主要介绍了重构的一些概念和一些简单的实例。这一次,详细的说下项目中的一个重构场景--给API设计扩展机制。目的就是为了方便以后能灵活应对需求的改变。

    2 年前
  • 重新开坑,在 react 中使用 composition API

    emmm大家好,那个,虽然最近新型肺炎,搞的人心惶惶,没啥动力写码 其实我也没啥可写的了,但是闲着也是闲着,然后记起来 smox 弃坑了还有一堆星星,想着怎么重新开坑 背景 smox 弃坑,不是我任性...

    8 个月前
  • 通过一个demo学习Vue 3 Composition API

    前言 9月18日,Vue 3.0正式发布。其中,Composition API可谓是新版本的一大亮点。本文将通过一个小demo简单介绍Composition API的主要功能和使用方式。

    9 天前
  • 足球特殊指数api接口示例

    分享下足球特殊指数数据,单双、总进球数、半全场赔率api接口示例,详情查看在线文档 接口返回的是Json数据,可以使用fastjson来解析。 package com.huaying.demo.she...

    10 个月前
  • 足球冠军指数 api接口示例

    分享下足球冠军指数API数据,接口示例如下,可查看[在线文档](https://www.shenlu88.com/doc.... 接口返回的是Json数据,可以使用fastjson来解析 pack...

    7 个月前
  • 超火js库: Lodash API例子 (持续更新~~~)

    lodash.js是一款超火的js库,在npm上平均周下载量达到了惊人的12,374,096,github start36K!大量框架都用到了lodash,包括拥有123kstart的vue 本文对...

    2 年前
  • 谷歌地图API:带有多个标记的自动中心地图

    MultiformeIngegno提出了一个问题:Google Maps API v3: auto-center map with multiple markers,或许与您遇到的问题类似。

    3 年前
  • 谷歌地图API的多标记等

    StackTraceYo提出了一个问题:Google Maps API Multiple Markers with Infowindows,或许与您遇到的问题类似。

    3 年前

官方社区

扫码加入 JavaScript 社区