欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3如何處理重復(fù)渲染代碼的問題

 更新時(shí)間:2024年01月18日 10:25:50   作者:前端成長指南  
這篇文章主要來和大家一起探討一下在Vue3項(xiàng)目中如何處理重復(fù)渲染代碼的問題,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

普通的場景

最近在做 Vue3 項(xiàng)目的時(shí)候,在思考一個(gè)小問題,其實(shí)是每個(gè)人都做過的一個(gè)場景,很簡單,看下方代碼

<template>
<div v-for="item in data" :key="item.age">
	<span>{[ item.name }}</span>
	<span>今年已經(jīng) </span>
	<span>{[ item.age }}</span>
	<span>歲啦</span>
</div>
</template>
<script setup lang="ts">
const data = new Array(20).fill(0).map((_, index) => ({
name:`sunshine-${index}`,
age: index
}));
</script>

其實(shí)就是一個(gè)普通的不能再普通的循環(huán)遍歷渲染的案例,咱們往下接著看,如果這樣的遍歷在同一個(gè)組件里出現(xiàn)了很多次,比如下方代碼

<template>
<div>
	<div v-for="item in data" :key="item.age">
		<span>{{ item.name }}</span>
		<span>今年已經(jīng) </span>
		<span>{{ item.age }}</span>
		<span>歲啦</span>
	</div>
	<!-- 多處使用 -->
	<div v-for="item in data" :key="item.age">
		<span>{[ item.name }}</span>
		<span>今年已經(jīng) </span>
		<span>{{ item.age }}</span>
		<span>歲啦</span>
	</div>
	<!-- 多處使用 -->
	<div v-for="item in data" :key="item.age">
		<span>{[ item.name }}</span>
		<span>今年已經(jīng) </span>
		<span>{[ item.age }}</span>
		<span>歲啦</span>
	</div>
	<!-- 多處使用 -->
	<div v-for="item in data" :key="item.age">
		<span>{ item.name }}</span>
		<span>今年已經(jīng) </span>
		<span>{[ item.age }}</span>
		<span>歲啦</span>
	</div>
</div>
</temple>

這個(gè)時(shí)候我們應(yīng)該咋辦呢?誒!很多人很快就能想出來了,那就是把循環(huán)的項(xiàng)抽取出來成一個(gè)組件,這樣就能減少很多代碼量了,比如我抽取成 Item.vue 這個(gè)組件

<!-- Item.vue -->
<template>
<div>
	<span>{{ name }}</span>
	<span>今年已經(jīng) </span>
	<span>{ age }}</span>
	<span>歲啦</span>
</div>
</template>
<script lang="ts" setup>defineProps({
name: {
type: String,
default:'',
},
age: {
type:Number
default:0,
};
})
</script>

然后直接可以引用并使用它,這樣大大減少了代碼量,并且統(tǒng)一管理,提高代碼可維護(hù)性!?。?/p>

<template>
<div>
<Item v-for="item in data" :key="item.age" :age="item.age" :name="item.name" /></div>
</template>
<script setup lang="ts">
import Item from './Item.vue';
const data = new Array(20).fill(0).map((_, index) => ({
name:`sunshine-${index}`,
age: index
</script>

不難受嗎?

但是我事后越想越難受,就一個(gè)這么丁點(diǎn)代碼量的我都得抽取成組件,那我不敢想象以后我的項(xiàng)目組件數(shù)會(huì)多到什么地步,而且組件粒度太細(xì),確實(shí)也增加了后面開發(fā)者的負(fù)擔(dān)~

那么有沒有辦法,可以不抽取成組件呢?我可以在當(dāng)前組件里去提取嗎,而不需要去重新定義一個(gè)組件呢?例如下面的效果

<template>
<div>
	<!-- 在本組件中定義一個(gè)復(fù)用模板 -->
	<DefineTemplate v-slot="[ age, name }">
		<div>
		<span>{{ name }}</span>
		<span>今年已經(jīng) </span>
		<span>{{ age }}</span>
		<span>歲啦</span>
		</div>
	</DefineTemplate>
	<!-- 可多次使用復(fù)用模板 -->
	<ReuseTemplate v-for="item in data" :key="item.age" :age-"item.age" :name-"item.name">
	<ReuseTemplate v-for="item in data" :key="item,age" :age="item,age" :name-"item, name">
	<ReuseTemplate v-for="item in data" :key="item.age" :age="item.age" :name="item.name">
</div>
</template>

<script setup lang="ts">
import { useTemplate } from '@/hooks/useTemplate';
const data = new Array(20).fill(0).map((_, index) => ({
name:`sunshine-$[index}`,
age: index,
});
const [DefineTemplate, ReuseTemplate] = useTemplate();
</script>

useTemplate 代碼實(shí)現(xiàn)

想到這,馬上行動(dòng)起來,需要封裝一個(gè) useTemplate來實(shí)現(xiàn)這個(gè)功能

import { defineComponent, shallowRef } from 'vue';
import { camelCase } from 'lodash';
import type { Slot } from 'vue';
//將橫線命名轉(zhuǎn)大小駝峰
function keysToCamelKebabCase(obj: Record<string,any>)[
	const newObj: typeof obj = ;for (const key in obj) newObj[camelCase(key)] = obj[key];
	return newObj;
}
export const useTemplate = () => {
	const render = shallowRef<Slot undefined>();
	const define = defineComponent({
	setup(_,[ slots }) {
		return () => {
			//將復(fù)用模板的渲染函數(shù)內(nèi)容保存起來
			render.value = slotsdefault;
			}
		}
	})
	const reuse = defineComponent({
		setup(_, [ attrs, slots }) {
			return () => {
				// 還沒定義復(fù)用模板,則拋出錯(cuò)誤
				if (!render.value){
					throw new Error( 你還沒定義復(fù)用模板呢!);
				}
				// 執(zhí)行渲染函數(shù),傳入 attrs、slots
				const vnode = render.value([ ...keysToCamelKebabCase(attrs), $slots: slots });
				return vnode.length === 1 ? vnode[0] : vnode;
			}
		},
	});
	return [define reuse];
}

用的不爽

盡管做到這個(gè)地步,我還是覺得用的不爽,因?yàn)闆]有類型提示

我們想要的是比較爽的使用,那肯定得把類型的提示給支持上?。。?!于是給 useTemplate 加上泛型??!加上之后就有類型提示啦~~~~

加上泛型后的 useTemplate 代碼如下:

import { defineComponent, shallowRef } from 'vue';
import { camelCase } from 'lodash';
import type { DefineComponent, Slot } from 'vue';

// 將橫線命名轉(zhuǎn)換為駝峰命名
function keysToCamelKebabCase(obj: Record<string, any>) {
  const newObj: typeof obj = {};
  for (const key in obj) newObj[camelCase(key)] = obj[key];
  return newObj;
}

// 定義 DefineTemplateComponent 類型,該類型表示定義模板的組件
export type DefineTemplateComponent<
  Bindings extends object,
  Slots extends Record<string, Slot | undefined>,
> = DefineComponent<object> & {
  new (): { $slots: { default(_: Bindings & { $slots: Slots }): any } };
};

// 定義 ReuseTemplateComponent 類型,該類型表示復(fù)用模板的組件
export type ReuseTemplateComponent<
  Bindings extends object,
  Slots extends Record<string, Slot | undefined>,
> = DefineComponent<Bindings> & {
  new (): { $slots: Slots };
};

// 定義 ReusableTemplatePair 類型,表示一個(gè)定義模板和復(fù)用模板的組件對
export type ReusableTemplatePair<
  Bindings extends object,
  Slots extends Record<string, Slot | undefined>,
> = [DefineTemplateComponent<Bindings, Slots>, ReuseTemplateComponent<Bindings, Slots>];

// useTemplate 函數(shù),返回一個(gè)定義模板和復(fù)用模板的組件對
export const useTemplate = <
  Bindings extends object,
  Slots extends Record<string, Slot | undefined> = Record<string, Slot | undefined>,
>(): ReusableTemplatePair<Bindings, Slots> => {
  const render = shallowRef<Slot | undefined>();

  // 定義 DefineTemplateComponent 組件
  const define = defineComponent({
    setup(_, { slots }) {
      return () => {
        // 將復(fù)用模板的渲染函數(shù)內(nèi)容保存起來
        render.value = slots.default;
      };
    },
  }) as DefineTemplateComponent<Bindings, Slots>;

  // 定義 ReuseTemplateComponent 組件
  const reuse = defineComponent({
    setup(_, { attrs, slots }) {
      return () => {
        // 還沒定義復(fù)用模板,則拋出錯(cuò)誤
        if (!render.value) {
          throw new Error('你還沒定義復(fù)用模板呢!');
        }
        // 執(zhí)行渲染函數(shù),傳入 attrs、slots
        const vnode = render.value({ ...keysToCamelKebabCase(attrs), $slots: slots });
        return vnode.length === 1 ? vnode[0] : vnode;
      };
    },
  }) as ReuseTemplateComponent<Bindings, Slots>;

  return [define, reuse];
};

以上就是Vue3如何處理重復(fù)渲染代碼的問題的詳細(xì)內(nèi)容,更多關(guān)于Vue3重復(fù)渲染的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue獲取表單數(shù)據(jù)的方法

    Vue獲取表單數(shù)據(jù)的方法

    這篇文章主要為大家介紹了Vue獲取表單數(shù)據(jù)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • 使用idea創(chuàng)建vue項(xiàng)目的圖文教程

    使用idea創(chuàng)建vue項(xiàng)目的圖文教程

    Vue.js是一套構(gòu)建用戶界面的框架,只關(guān)注視圖層,它不僅易于上手,還便于與第三方庫或既有項(xiàng)目整合,下面這篇文章主要給大家介紹了關(guān)于使用idea創(chuàng)建vue項(xiàng)目的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • nginx配置域名后的二級(jí)目錄訪問不同項(xiàng)目的配置操作

    nginx配置域名后的二級(jí)目錄訪問不同項(xiàng)目的配置操作

    這篇文章主要介紹了nginx配置域名后的二級(jí)目錄訪問不同項(xiàng)目的配置操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Vue echarts畫甘特圖流程詳細(xì)講解

    Vue echarts畫甘特圖流程詳細(xì)講解

    這篇文章主要介紹了Vue echarts畫甘特圖流程,甘特圖(Gantt chart)又稱為橫道圖、條狀圖(Bar chart)。其通過條狀圖來顯示項(xiàng)目、進(jìn)度和其他時(shí)間相關(guān)的系統(tǒng)進(jìn)展的內(nèi)在關(guān)系隨著時(shí)間進(jìn)展的情況
    2022-09-09
  • Vue模擬數(shù)據(jù),實(shí)現(xiàn)路由進(jìn)入商品詳情頁面的示例

    Vue模擬數(shù)據(jù),實(shí)現(xiàn)路由進(jìn)入商品詳情頁面的示例

    今天小編就為大家分享一篇Vue模擬數(shù)據(jù),實(shí)現(xiàn)路由進(jìn)入商品詳情頁面的示例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • Vue?warn:Property?"state"?was?accessed?during?render解決

    Vue?warn:Property?"state"?was?accessed?during

    這篇文章主要為大家介紹了Vue?warn:Property?"state"?was?accessed?during?render的報(bào)錯(cuò)解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 解決removeEventListener 無法清除監(jiān)聽的問題

    解決removeEventListener 無法清除監(jiān)聽的問題

    這篇文章主要介紹了解決removeEventListener 無法清除監(jiān)聽的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • 關(guān)于vue-tree-chart簡單的使用

    關(guān)于vue-tree-chart簡單的使用

    這篇文章主要介紹了關(guān)于vue-tree-chart簡單的使用方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Vue3全局配置Axios并解決跨域請求問題示例詳解

    Vue3全局配置Axios并解決跨域請求問題示例詳解

    axios 是一個(gè)基于promise的HTTP庫,支持promise所有的API,本文給大家介紹Vue3全局配置Axios并解決跨域請求問題,內(nèi)容從axios部署開始到解決跨域問題,感興趣的朋友一起看看吧
    2023-11-11
  • Vue3+vuedraggable實(shí)現(xiàn)動(dòng)態(tài)配置頁面

    Vue3+vuedraggable實(shí)現(xiàn)動(dòng)態(tài)配置頁面

    這篇文章主要為大家詳細(xì)介紹了Vue3如何利用vuedraggable實(shí)現(xiàn)動(dòng)態(tài)配置頁面,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下
    2023-12-12

最新評論