写点什么

Vue3.x 关于组件的那些变化(新手必看篇)

用户头像
码仔
关注
发布于: 11 小时前
Vue3.x 关于组件的那些变化(新手必看篇)

一、组件内的 data 为什么总是函数形式?

我们试着先做一个计数器案例,把 data 的返回形式修改成一个对象。具体的代码如下:

<template> <div>  <button @click="num++">+</button>   {{num}}  <button @click="num--">-</button> </div></template><script>const retData = { num:0}export default { data(){  return retData }}</script>
复制代码

运行结果,看着是正常的,并无异常。但我们都知道,vue 项目中,之所以采用组件形式,就是为了重复多次使用,所以我们多次使用我们的组件试试。

神奇的效果发生了,当我们改变第一个组件的数值时,第二个组件的数据也被修改。修改第二个组件的时候,第一个组件的数据也同步更新。


原因:同一个组件被复用多次,会创建多个实例,如果 data 是一个对象的话,这些实例用的是同一个构造函数,指针指向的就会是同一个地方,就导致了两个组件的数据会同时更新。

为了保证组件内的数据各自独立,不会相互影响,要求每个组件的 data 必须是函数形式,目的就是把数据放入一个新对象内,这样就不会出现上述问题了。

说这的主要意义就是告诉我们,在 Vue3.x 中的 data 选项总是为函数形式,返回响应式数据。

Vue2.x VS Vue3.x 实例创建


二、函数式组件的变化

在 Vue3.x 中,functional:true 组件选项被移除。vue3.x 不推荐使用函数式组件。

有些小伙伴就会惊叹,妈呀,俺都不知道函数式组件是啥,你说得再简单我也不懂呐,所以就讲讲函数式组件干啥的,原来的 functional 属性放哪?

2.1、在 Vue2.x 中的函数式组件:

函数式组件也是组件的一种类型,主要用来定义那些没有响应数据,也不需要任何生命周期钩子函数,只 props 来接收传递来的数据。

类型 1:基于模板的函数式组件

<template functional > <div>  函数式组件内容 </div></template>
复制代码

类型 2:组件注册

Vue.componenet('fun-comp':{ functional:true, props:{  msg:{   type:String,   default:'组件数据'  } }, render:(h,context)=>{  return h('div',['组件内容','++',context.props.msg]) }})
复制代码

类型 3:中间件实现 render 方法

// FunComps.js 文件代码export default { functional:true, props:{  render:{   type:Function  },  params:{} }, render:(h,ctx)=>{  return ctx.props.render(h,ctx.props.params) }}
//组件调用<fun-comp :render="renderHandle" :params="['111','222']" />
复制代码

renderHandle 这个函数,在外层可以任意控制,这样不但节省开销,而且复用性也很高。

2.2、在 Vue3.x 中的函数式组件:

在 SFC 中不能使用 functional 特性声明是函数式组件,移除了 functional:true 特性。

// 新建一个 FunComp.vue 文件<script>import { h } from "vue"function Footer(props,context){ return h(`h${props.level}`,context.attrs , context.slots )}Footer.props = ['level']export default Footer</script>
//使用函数式组件<template> <FunComp level="1.0.0" >Vue3.x函数式组件内容</FunComp></template><script >import FunComp from '../../components/FunComp.vue'export default{ component:{ FunComp },}</script>
复制代码

这下应该清楚到底移除的属性在哪了!接着看看异步组件有什么改变。。。

三、异步组件的变化

Vue3.x 异步组件要求使用 defineAsyncComponent 方法创建。

由于 Vue3 中函数式组件必须定义为纯函数,所以异步组件有如下变化:

  1. 必须明确地使用 defineAsyncComponent 方法包裹

  2. component 选项已经被重命名为 loader

  3. loader 函数不再接收 resolve 和 reject 回调方法 。且必须返回一个 Promise 对象 。

3.1、不带配置的异步组件对比

在 Vue2.x 中异步组件使用:

{ path:'/', component: ()=> import("@/view/home/index")}
复制代码

在 Vue3.x 中异步组件使用:

import { defineAsyncComponent } from 'vue'
{ path:"/", component:defineAsyncComponent(()=>{ import("@/view/home/index.vue") })}
复制代码

3.2、带配置的异步组件

const asyncPageWithOptions = defineAsyncComponent({ loader:()=> import("../view/index/index.vue"), delay:200, timeout:3000, errorComponent:ErrorComponent, loadingComponent:LoadingComponent})
复制代码

loader 选项是以前的 component 选项。

四、自定义组件白名单的变化

Vue3.x 中,自定义元素检测发生在模板编译时,如果要添加 vue 之外的自定义元素,需要在编译器选项中设置 isCustomElement 选项。使用构建工具时,模板都会用 vue-loader 预编译,在 vite.config.js 中配置它提供的 vueCompilerOption 即可:

import { defineConfig,vueCompilerOption } from 'vite'import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/export default defineConfig({ plugins: [vue()], vueCompilerOptions:{ isCustomElement:tag => tag==='pie-chart' }})
复制代码

此时遇到 pie-chart 元素时,直接跳过,不对其进行编译。

五、动态组件

vue3.x 中设置动态组件时,is 属性只能用于 component 标签上。

使用方法:

<component :is="currentView"></component>//currentView 是一个表达式
复制代码

让多个组件使用同一个挂载点,并动态切换组件。

5.1、动态组件的缓存

好多时候多个组件来回切换时,组件的实例都是重新创建的,而我们需要保存它的状态,此时就需要缓存动态组件。

在 Vue2.x 中:

<keep-alive> <component :is="currentView"></component></keep-alive>
复制代码

在 Vue3.x 中:keep-alive 必须使用在 router-view 内部

<router-view><keep-alive> <component :is="currentView"></component> </keep-alive></router-view>
复制代码


发布于: 11 小时前阅读数: 7
用户头像

码仔

关注

还未添加个人签名 2019.06.26 加入

还未添加个人简介

评论

发布
暂无评论
Vue3.x 关于组件的那些变化(新手必看篇)