电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

詳解Vue組件復(fù)用和擴(kuò)展之道

瀏覽:14日期:2022-09-30 10:28:05
概述

軟件編程有一個(gè)重要的原則是 D.R.Y(Don’t Repeat Yourself),講的是盡量復(fù)用代碼和邏輯,減少重復(fù)。組件擴(kuò)展可以避免重復(fù)代碼,更易于快速開(kāi)發(fā)和維護(hù)。那么,擴(kuò)展 Vue 組件的最佳方法是什么?

Vue 提供了不少 API 和模式來(lái)支持組件復(fù)用和擴(kuò)展,你可以根據(jù)自己的目的和偏好來(lái)選擇。

本文介紹幾種比較常見(jiàn)的方法和模式,希望對(duì)你有所幫助。

擴(kuò)展組件是否必要

要知道,所有的組件擴(kuò)展方法都會(huì)增加復(fù)雜性和額外代碼,有時(shí)候還會(huì)增加性能消耗。

因此,在決定擴(kuò)展組件之前,最好先看看有沒(méi)有其他更簡(jiǎn)單的設(shè)計(jì)模式能完成目標(biāo)。

下面幾種組件設(shè)計(jì)模式通常足夠替代擴(kuò)展組件了:

props 配合模板邏輯 slot 插槽 JavaScript 工具函數(shù)

props 配合模板邏輯

最簡(jiǎn)單的方法是通過(guò)props結(jié)合模板條件渲染,來(lái)實(shí)現(xiàn)組件的多功能。

比如通過(guò) type 屬性:MyVersatileComponent.vue

<template> <div class='wrapper'> <div v-if='type === ’a’'>...</div> <div v-else-if='type === ’b’'>...</div> <!--etc etc--> </div></template><script>export default { props: { type: String }, ...}</script>

使用組件的時(shí)候傳不同的type值就能實(shí)現(xiàn)不同的結(jié)果。

// *ParentComponent.vue*<template> <MyVersatileComponent type='a' /> <MyVersatileComponent type='b' /></template>

如果出現(xiàn)下面兩種情況,就說(shuō)明這種模式不適用了,或者用法不對(duì):

組件組合模式把狀態(tài)和邏輯分解成原子部分,從而讓?xiě)?yīng)用具備可擴(kuò)展性。如果組件內(nèi)存在大量條件判斷,可讀性和可維護(hù)性就會(huì)變差。 props 和模板邏輯的本意是讓組件動(dòng)態(tài)化,但是也存在運(yùn)行時(shí)資源消耗。如果你利用這種機(jī)制在運(yùn)行時(shí)解決代碼組合問(wèn)題,那是一種反模式。slot(插槽)

另一種可避免組件擴(kuò)展的方式是利用 slots(插槽),就是讓父組件在子組件內(nèi)設(shè)置自定義內(nèi)容。

// *MyVersatileComponent.vue*<template> <div class='wrapper'> <h3>Common markup</div> <slot /> </div></template>

// *ParentComponent.vue*<template> <MyVersatileComponent> <h4>Inserting into the slot</h4> </MyVersatileComponent></template>

渲染結(jié)果:

<div class='wrapper'> <h3>Common markup</div> <h4>Inserting into the slot</h4></div>

這種模式有一個(gè)潛在約束, slot 內(nèi)的元素從屬于父組件的上下文,在拆分邏輯和狀態(tài)時(shí)可能不太自然。scoped slot會(huì)更靈活,后面會(huì)在無(wú)渲染組件一節(jié)里提到。

JavaScript 工具函數(shù)

如果只需要在各組件之間復(fù)用獨(dú)立的函數(shù),那么只需要抽取這些 JavaScript 模塊就行了,根本不需要用到組件擴(kuò)展模式。

JavaScript 的模塊系統(tǒng)是一種非常靈活和健壯的代碼共享方式,所以你應(yīng)該盡可能地依靠它。MyUtilityFunction.js

export default function () { ...}

MyComponent.vue

import MyUtilityFunction from './MyUtilityFunction';export default { methods: { MyUtilityFunction }}擴(kuò)展組件的幾種模式

如果你已經(jīng)考慮過(guò)以上幾種簡(jiǎn)單的模式,但這些模式還不夠靈活,無(wú)法滿足需求。那么就可以考慮擴(kuò)展組件了。

擴(kuò)展 Vue 組件最流行的方法有以下四種:

Composition 函數(shù) mixin 高階組件(HOC) 無(wú)渲染組件

每一種方法都有其優(yōu)缺點(diǎn),根據(jù)使用場(chǎng)景,或多或少都有適用的部分。

Composition API

組件之間共享狀態(tài)和邏輯的最新方案是 Composition API。這是 Vue 3 推出的 API,也可以在 Vue 2 里當(dāng)插件使用。

跟之前在組件定義配置對(duì)象里聲明data,computed,methods等屬性的方式不同,Composition API 通過(guò)一個(gè) setup 函數(shù)聲明和返回這些配置。

比如,用 Vue 2 配置屬性的方式聲明 Counter 組件是這樣的:Counter.vue

<template> <button @click='increment'> Count is: {{ count }}, double is: {{ double }} </button><template><script>export default { data: () => ({ count: 0 }), methods: { increment() { this.count++; } }, computed: { double () { return this.count * 2; } }}</script>

用 Composition API 重構(gòu)這個(gè)組件,功能完全一樣:Counter.vue

<template><!--as above--><template><script>import { reactive, computed } from 'vue';export default { setup() { const state = reactive({ count: 0, double: computed(() => state.count * 2) }); function increment() { state.count++ } return { count, double, increment } }}</script>

用 Composition API 聲明組件的主要好處之一是,邏輯復(fù)用和抽取變得非常輕松。

進(jìn)一步重構(gòu),把計(jì)數(shù)器的功能移到 JavaScript 模塊 useCounter.js中:useCounter.js

import { reactive, computed } from 'vue';export default function { const state = reactive({ count: 0, double: computed(() => state.count * 2) }); function increment() { state.count++ } return { count, double, increment }}

現(xiàn)在,計(jì)數(shù)器功能可以通過(guò)setup函數(shù)無(wú)縫引入到任意 Vue 組件中:MyComponent.vue

<template><!--as above--></template><script>import useCounter from './useCounter';export default { setup() { const { count, double, increment } = useCounter(); return { count, double, increment } }}</script>

Composition 函數(shù)讓功能模塊化、可重用,是擴(kuò)展組件最直接和低成本的方式。

Composition API 的缺點(diǎn)

Composition API 的缺點(diǎn)其實(shí)不算什么——可能就是看起來(lái)有點(diǎn)??攏?⑶倚碌撓梅ǘ砸恍 Vue 開(kāi)發(fā)者來(lái)說(shuō)有點(diǎn)陌生。

關(guān)于 Composition API 優(yōu)缺點(diǎn)的討論,推薦閱讀:When To Use The New Vue Composition API (And When Not To)

mixin

如果你還在用 Vue 2,或者只是喜歡用配置對(duì)象的方式定義組件功能,可以用 mixin 模式。mixin 把公共邏輯和狀態(tài)抽取到單獨(dú)的對(duì)象,跟使用 mixin 的組件內(nèi)部定義對(duì)象合并。

我們繼續(xù)用之前的Counter組件例子,把公共邏輯和狀態(tài)放到CounterMixin.js模塊中。CounterMixin.js

export default { data: () => ({ count: 0 }), methods: { increment() { this.count++; } }, computed: { double () { return this.count * 2; } }}

使用 mixin 也很簡(jiǎn)單,只要導(dǎo)入對(duì)應(yīng)模塊并在mixins數(shù)組里加上變量就行。組件初始化時(shí)會(huì)把 mixin 對(duì)象與組件內(nèi)部定義對(duì)象合并。MyComponent.vue

import CounterMixin from './CounterMixin';export default { mixins: [CounterMixin], methods: { decrement() { this.count--; } }}

選項(xiàng)合并

如果組件內(nèi)的選項(xiàng)跟 mixin 沖突怎么辦?

比如,給組件定義一個(gè)自帶的increment方法,哪個(gè)優(yōu)先級(jí)更高呢?MyComponent.vue

import CounterMixin from './CounterMixin';export default { mixins: [CounterMixin], methods: { // 自帶的 `increment`` 方法會(huì)覆蓋 mixin 的`increment` 嗎? increment() { ... } }}

這個(gè)時(shí)候就要說(shuō)到 Vue 的合并策略了。Vue 有一系列的規(guī)則,決定了如何處理同名選項(xiàng)。

通常,組件自帶的選項(xiàng)會(huì)覆蓋來(lái)自 mixin 的選項(xiàng)。但也有例外,比如同類型的生命周期鉤子,不是直接覆蓋,而是都放進(jìn)數(shù)組,按順序執(zhí)行。

你也可以通過(guò) 自定義合并策略 改變默認(rèn)行為。

mixin 的缺點(diǎn)

作為擴(kuò)展組件的一種模式,mixin 對(duì)于簡(jiǎn)單的場(chǎng)景還算好用,一旦規(guī)模擴(kuò)大,問(wèn)題就來(lái)了。不僅需要注意命名沖突問(wèn)題(尤其是第三方 mixin),使用了多個(gè) mixin 的組件,很難搞清楚某個(gè)功能到底來(lái)自于哪里,定位問(wèn)題也比較困難。

高階組件

高階組件(HOC)是從 React 借用的概念,Vue 也能使用。

為了理解這個(gè)概念,我們先拋開(kāi)組件,看看兩個(gè)簡(jiǎn)單的 JavaScript 函數(shù),increment和 double。

function increment(x) { return x++;}function double(x) { return x * 2;}

假設(shè)我們想給這兩個(gè)函數(shù)都加一個(gè)功能:在控制臺(tái)輸出結(jié)果。

為此,我們可以用高階函數(shù)模式,新建一個(gè)addLogging函數(shù),接受函數(shù)作為參數(shù),并返回一個(gè)帶有新增功能的函數(shù)。

function addLogging(fn) { return function(x) { const result = fn(x); console.log('The result is: ', result); return result; };}const incrementWithLogging = addLogging(increment);const doubleWithLogging = addLogging(double);

組件如何利用這種模式呢?類似地,我們創(chuàng)建一個(gè)高階組件來(lái)渲染Counter組件,同時(shí)添加一個(gè)decrement方法作為實(shí)例屬性。

實(shí)際代碼比較復(fù)雜,這里只給出偽代碼作為示意:

import Counter from './Counter';// 偽代碼const CounterWithDecrement => ({ render(createElement) { const options = { decrement() {this.count--; } } return createElement(Counter, options); }});

HOC 模式比 mixin 更簡(jiǎn)潔,擴(kuò)展性更好,但是代價(jià)是增加了一個(gè)包裹組件,實(shí)現(xiàn)起來(lái)也需要技巧。

無(wú)渲染組件

如果需要在多個(gè)組件上使用相同的邏輯和狀態(tài),只是展示方式不同,那么就可以考慮無(wú)渲染組件模式。

該模式需要用到兩類組件:邏輯組件用于聲明邏輯和狀態(tài),展示組件用于展示數(shù)據(jù)。

邏輯組件

還是回到Counter的例子,假設(shè)我們需要在多個(gè)地方重用這個(gè)組件,但是展示方式不同。

創(chuàng)建一個(gè)CounterRenderless.js用于定義邏輯組件,包含邏輯和狀態(tài),但是不包含模板,而是通過(guò) render函數(shù)聲明 scoped slot。

scoped slot暴露三個(gè)屬性給父組件使用:狀態(tài)count,方法increment 和計(jì)算屬性 double。CounterRenderless.js

export default { data: () => ({ count: 0 }), methods: { increment() { this.count++; } }, computed: { double () { return this.count * 2; } }, render() { return this.$scopedSlots.default({ count: this.count, double: this.double, increment: this.toggleState, }) }}

這里的scoped slot是這種模式里邏輯組件的關(guān)鍵所在。

展示組件

接下來(lái)是展示組件,作為無(wú)渲染組件的使用方,提供具體的展示方式。

所有的元素標(biāo)簽都包含在scoped slot里。可以看到,這些屬性在使用上跟模板直接放在邏輯組件里沒(méi)什么兩樣。CounterWithButton.vue

<template> <counter-renderless slot-scope='{ count, double, increment }'> <div>Count is: {{ count }}</div> <div>Double is: {{ double }}</div> <button @click='increment'>Increment</button> </counter-renderless></template><script>import CounterRenderless from './CountRenderless';export default { components: { CounterRenderless }}</script>

無(wú)渲染組件模式非常靈活,也容易理解。但是,它沒(méi)有前面那幾種方法那么通用,可能只有一種應(yīng)用場(chǎng)景,那就是用于開(kāi)發(fā)組件庫(kù)。

模板擴(kuò)展

上面的 API 也好,設(shè)計(jì)模式也罷,都有一種局限性,就是無(wú)法擴(kuò)展組件的模板。Vue 在邏輯和狀態(tài)方面有辦法重用,但是對(duì)于模板標(biāo)簽就無(wú)能為力了。

有一種比較 hack 的方式,就是利用 HTML 預(yù)處理器,比如 Pug,來(lái)處理模板擴(kuò)展。

第一步是創(chuàng)建一個(gè)基礎(chǔ)模板.pug文件,包含公共的頁(yè)面元素。還要包含一個(gè)block input,作為模板擴(kuò)展的占位符。

BaseTemplate.pug

div.wrapper h3 {{ myCommonProp }} <!--common markup--> block input <!--extended markup outlet -->

為了能擴(kuò)展這個(gè)模板,需要安裝 Vue Loader 的 Pug 插件。然后就可以引入基礎(chǔ)模板并利用block input語(yǔ)法替換占位部分了:MyComponent.vue

<template lang='pug'> extends BaseTemplate.pug block input h4 {{ myLocalProp }} <!--gets included in the base template--></template>

一開(kāi)始你可能會(huì)認(rèn)為它跟 slot 的概念是一樣的,但是有個(gè)區(qū)別,這里的基礎(chǔ)模板不屬于任何單獨(dú)的組件。它在編譯時(shí)跟當(dāng)前組件合并,而不是像 slot 那樣是在運(yùn)行時(shí)替換。

以上就是詳解Vue組件復(fù)用和擴(kuò)展之道的詳細(xì)內(nèi)容,更多關(guān)于Vue組件復(fù)用和擴(kuò)展的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 集装袋吨袋生产厂家-噸袋廠傢-塑料编织袋-纸塑复合袋-二手吨袋-太空袋-曹县建烨包装 | 新材料分散-高速均质搅拌机-超声波分散混合-上海化烁智能设备有限公司 | ZHZ8耐压测试仪-上海胜绪电气有限公司 | 杭州门窗厂家_阳光房_包阳台安装电话-杭州窗猫铝合金门窗 | 机器视觉检测系统-视觉检测系统-机器视觉系统-ccd检测系统-视觉控制器-视控一体机 -海克易邦 | 金环宇|金环宇电线|金环宇电缆|金环宇电线电缆|深圳市金环宇电线电缆有限公司|金环宇电缆集团 | 泥沙分离_泥沙分离设备_泥砂分离机_洛阳隆中重工机械有限公司 | 干粉砂浆设备_干混砂浆生产线_腻子粉加工设备_石膏抹灰砂浆生产成套设备厂家_干粉混合设备_砂子烘干机--郑州铭将机械设备有限公司 | 国资灵活用工平台_全国灵活用工平台前十名-灵活用工结算小帮手 | 杭州代理记账多少钱-注册公司代办-公司注销流程及费用-杭州福道财务管理咨询有限公司 | 南京和瑞包装有限公司| 对辊式破碎机-对辊制砂机-双辊-双齿辊破碎机-巩义市裕顺机械制造有限公司 | 匀胶机旋涂仪-声扫显微镜-工业水浸超声-安赛斯(北京)科技有限公司 | 安徽华耐泵阀有限公司-官方网站 安德建奇火花机-阿奇夏米尔慢走丝|高维|发那科-北京杰森柏汇 | 高精度-恒温冷水机-螺杆式冰水机-蒸发冷冷水机-北京蓝海神骏科技有限公司 | 电销卡_稳定企业大语音卡-归属地可选-世纪通信 | 登车桥动力单元-非标液压泵站-非标液压系统-深圳市三好科技有限公司 | 软文发布平台 - 云软媒网络软文直编发布营销推广平台 | 升降机-高空作业车租赁-蜘蛛车-曲臂式伸缩臂剪叉式液压升降平台-脚手架-【普雷斯特公司厂家】 | 多功能真空滤油机_润滑油全自动滤油机_高效真空滤油机价格-重庆润华通驰 | 压砖机、液压制砖机、静压砖机、环保砖机生产厂家—杜甫机械 | 鄂泉泵业官网|(杭州、上海、全国畅销)大流量防汛排涝泵-LW立式排污泵 | 硅胶制品-硅橡胶制品-东莞硅胶制品厂家-广东帝博科技有限公司 | 苏州防水公司_厂房屋面外墙防水_地下室卫生间防水堵漏-苏州伊诺尔防水工程有限公司 | 便携式高压氧舱-微压氧舱-核生化洗消系统-公众洗消站-洗消帐篷-北京利盟救援 | 安平县鑫川金属丝网制品有限公司,声屏障,高速声屏障,百叶孔声屏障,大弧形声屏障,凹凸穿孔声屏障,铁路声屏障,顶部弧形声屏障,玻璃钢吸音板 | 知名电动蝶阀,电动球阀,气动蝶阀,气动球阀生产厂家|价格透明-【固菲阀门官网】 | 涂层测厚仪_漆膜仪_光学透过率仪_十大创新厂家-果欧电子科技公司 | 楼承板设备-楼承板成型机-免浇筑楼承板机器厂家-捡来 | SF6环境监测系统-接地环流在线监测装置-瑟恩实业 | 闭端端子|弹簧螺式接线头|防水接线头|插线式接线头|端子台|电源线扣+护线套|印刷电路板型端子台|金笔电子代理商-上海拓胜电气有限公司 | 播音主持培训-中影人教育播音主持学苑「官网」-中国艺考界的贵族学校 | 乐泰胶水_loctite_乐泰胶_汉高乐泰授权(中国)总代理-鑫华良供应链 | 工作服定制,工作服定做,工作服厂家-卡珀职业服装(苏州)有限公司 | 防渗膜厂家|养殖防渗膜|水产养殖防渗膜-泰安佳路通工程材料有限公司 | 深圳离婚律师咨询「在线免费」华荣深圳婚姻律师事务所专办离婚纠纷案件 | 香港新时代国际美容美发化妆美甲培训学校-26年培训经验,值得信赖! | 山东信蓝建设有限公司官网 | 「银杏树」银杏树行情价格_银杏树种植_山东程锦园林 | 百度关键词优化_网站优化_SEO价格 - 云无限好排名 | 预制舱-电力集装箱预制舱-模块化预制舱生产厂家-腾达电器设备 |