从Vue2到Vue3学习汇总知识点(四):不兼容的变更之组件与渲染函数

15 篇文章 0 订阅
14 篇文章 0 订阅

不兼容的变更之组件与渲染函数

1、只能使用普通函数创建函数式组件

在 3.x 中,2.x 带来的函数式组件的性能提升可以忽略不计,因此我们建议只使用有状态的组件
函数式组件只能由接收 props 和 context (即:slots、attrs、emit) 的普通函数创建
非兼容:functional attribute 已从单文件组件 (SFC) 的 中移除
非兼容:{ functional: true } 选项已从通过函数创建的组件中移除
2.x 语法

// Vue 2 函数式组件示例
export default {
  functional: true,
  props: ['level'],
  render(h, { props, data, children }) {
    return h(`h${props.level}`, data, children)
  }
}

3.x语法

现在,在 Vue 3 中,所有的函数式组件都是用普通函数创建的。换句话说,不需要定义 { functional: true } 组件选项。
它们将接收两个参数:props 和 context。context 参数是一个对象,包含组件的 attrs、slots 和 emit property。
此外,h 现在是全局导入的,而不是在 render 函数中隐式提供。

import { h } from 'vue'

const DynamicHeading = (props, context) => {
  return h(`h${props.level}`, context.attrs, context.slots)
}

DynamicHeading.props = ['level']

export default DynamicHeading

2、异步组件

新的 defineAsyncComponent 助手方法,用于显式地定义异步组件
component 选项被重命名为 loader
Loader 函数本身不再接收 resolve 和 reject 参数,且必须返回一个 Promise

2.x 语法

const asyncModal = () => import('./Modal.vue')
** 或者带有选项
const asyncModal = {
  component: () => import('./Modal.vue'),
  delay: 200,
  timeout: 3000,
  error: ErrorComponent,
  loading: LoadingComponent
}

3.x语法

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

// 不带选项的异步组件
const asyncModal = defineAsyncComponent(() => import('./Modal.vue'))

// 带选项的异步组件
const asyncModalWithOptions = defineAsyncComponent({
  loader: () => import('./Modal.vue'),
  delay: 200,
  timeout: 3000,
  errorComponent: ErrorComponent,
  loadingComponent: LoadingComponent
})
// () =>
//    new Promise((resolve, reject) => {
//    })

Vue Router 支持一个类似的机制来异步加载路由组件,也就是俗称的懒加载。尽管类似,但是这个功能和 Vue 所支持的异步组件是不同的。当用 Vue Router 配置路由组件时,你不应该使用 defineAsyncComponent。
关于路由懒加载的传送门

3、 组件内的emits选项

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

<template>
  <div>
    <p>{{ text }}</p>
    <button v-on:click="$emit('accepted')">OK</button>
  </div>
</template>
<script>
  export default {
    props: ['text'],
    emits: ['accepted']
  }
</script>

强烈建议使用 emits 记录每个组件所触发的所有事件。因为移除了 .native 修饰符。任何未在 emits 中声明的事件监听器都会被算入组件的 $attrs,并将默认绑定到组件的根节点上。
这会导致一些原生事件触发两次,一次是在根元素上的原生事件,一次是组件内部的emit。

4、渲染函数 API

  • 渲染函数参数
**2.x 中,render 函数会自动接收 h 函数 (它是 createElement 的惯用别名) 作为参数:
export default {
 render(h) {
   return h('div')
 }
}
**3.x 中,h 函数现在是全局导入的,而不是作为参数自动传递。
import { h } from 'vue'
export default {
 render() {
   return h('div')
 }
}
  • 渲染函数签名更改
**2.x 中,render 函数自动接收参数,如 h 函数。
export default {
render(h) {
  return h('div')
}
}
**3.x 中,由于 render 函数不再接收任何参数,它将主要在 setup() 函数内部使用。
** 这还有一个好处:可以访问在作用域中声明的响应式状态和函数,以及传递给 setup() 的参数。
import { h, reactive } from 'vue'
export default {
setup(props, { slots, attrs, emit }) {
  const state = reactive({
    count: 0
  })
  function increment() {
    state.count++
  }
  // 返回渲染函数
  return () =>
    h(
      'div',
      {
        onClick: increment
      },
      state.count
    )
}
}
  • VNode Prop 格式化
**2.x 中,domProps 包含 VNode prop 中的嵌套列表:
{
  staticClass: 'button',
  class: { 'is-outlined': isOutlined },
  staticStyle: { color: '#34495E' },
  style: { backgroundColor: buttonColor },
  attrs: { id: 'submit' },
  domProps: { innerHTML: '' },
  on: { click: submitForm },
  key: 'submit-button'
}
**3.x 中,整个 VNode prop 的结构都是扁平的。
{
  class: ['button', { 'is-outlined': isOutlined }],
  style: [{ color: '#34495E' }, { backgroundColor: buttonColor }],
  id: 'submit',
  innerHTML: '',
  onClick: submitForm,
  key: 'submit-button'
}
  • 注册组件
**2.x 中,注册一个组件后,把组件名作为字符串传递给渲染函数的第一个参数,它可以正常地工作: 
export default {
 render(h) {
   return h('button-counter')
 }
}
**3.x 中,由于 VNode 是上下文无关的,不能再用字符串 ID 隐式查找已注册组件。
** 取而代之的是,需要使用一个导入的 resolveComponent 方法:
import { h, resolveComponent } from 'vue'

export default {
 setup() {
   const ButtonCounter = resolveComponent('button-counter')
   return () => h(ButtonCounter)
 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值