日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

vue 模板_简化版的 vue 页面模板语法

發布時間:2023/11/27 生活经验 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue 模板_简化版的 vue 页面模板语法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡化的目的:

  • 展現和邏輯分離。讓頁面模板文件僅僅和展現相關,從而方便做為 GUI Designer / 設計師工具的文件格式。
  • 簡化語法變種,方便 transpile 到不同的運行時平臺,例如微信小程序。
  • 修復了 jsx 語法不方便表達模板之間的 slot 組合關系的問題

簡化后的頁面模板使用體驗大致如下所述

展現和邏輯分離

和 .vue 一個單文件定義組件不同,我們把組件拆分為 .tm 和 .ts 兩個文件,例如

SomeComponent.tm
<html><body><div :title="myTitle" /></body>
</html>
SomeComponent.ts
import * as Biz from '@triones/biz-kernel';
export class SomeComponent extends Biz.MarkupView {public readonly myProp1: string;public readonly myProp2?: string;public get myTitle() {return '..some title...' + this.myProp1;}
}

當調用 SomeComponent 組件的時候,會創建對應的 SomeComponent.ts 這個類的實例。然后渲染頁面的時候,會用 SomeComponent.tm 來渲染。通過 :title 這樣的屬性來綁定“展現”和“邏輯”,渲染的時候 get myTitle() 這個 getter 屬性會被求值。

調用組件可以傳參,例如

<SomeComponent myProp1="hello" />

這個時候,從 public readonly myProp1: string 上就可以取到傳入的 myProp1 屬性。沒有傳的 myProp2 屬性就是 undefined。

對于事件處理,需要做如下聲明

SomeComponent.tm
<html><body><button @onClick="sayHello">hello</button></body>
</html>
SomeComponent.ts
import * as Biz from '@triones/biz-kernel';
export class SomeComponent extends Biz.MarkupView {public sayHello() {// ...}
}

和 vue 類似的是都是用 : 和 @ 來表達屬性綁定和事件處理。和 vue 不同的是,在綁定的地方只能寫屬性名字引用對應的屬性,不能寫復雜的表達式。和微信的 wxml 語法類似,bind:tap 這樣的事件綁定的地方,也是只能寫一個 event handler 的方法名,不能寫表達式。

習慣了在頁面模板里寫大量邏輯代碼的同學會非常不習慣,覺得這是開歷史的倒車。但是把邏輯從頁面模板里分離之后,這個純展示的頁面模板是非常適合做為 GUI Designer 的持久化格式的,或者從 sketch / figma 這樣的設計師工具導出。

零散小組件

為了避免寫很多組件,要建很多文件。我們可以把相關的小組件,合并寫在一個大文件里。例如這樣

<template #default><Header /><Body /><Footer />
</template
<template #Header>...
</template>
<template #Body>...
</template>
<template #Footer>...
</template>

這么寫就省得建立 4 個組件了,合并寫到一個組件里。如果沒有寫 <template #default>,那默認就是包裹在 <template #default> 里的。從語法上來說,也非常類似微信小程序的 wxml 的寫法。只是微信小程序的 wxml 沒有 <template #default>,而是直接寫在了文件的頂層。

也就是這么寫

<div>hello</div>

和這么寫

<template #default><div>hello</div>
</template>

是等價的

給父組件傳復雜參數

在 react / vue 中一個非常常見的做法是用 children 來表達數據屬性。例如

<LineChart width={500} height={300} data={data}><XAxis dataKey="name"/><YAxis/><CartesianGrid stroke="#eee" strokeDasharray="5 5"/>
</LineChart>

如果是 react 組件,往往會用 React.Children 來遍歷這些子節點,從中提取數據做為參數來使用。也就是給一個組件傳遞 children,有的時候傳的是組件,有的時候傳的是渲染組件的函數,有的時候傳遞過去被當成 array/object 使用。這也是 jsx 語法從一開始沒有設計好的地方。

這個問題的實質是類 html 語法,限定了屬性是簡單的字符串。如果我們這么寫:

<LineChart XAxis="{ dataKey: "name" }" YAxis CartesianGrid="{ stroke: "#eee", strokeDasharray="5 5" } />

書寫體驗會非常難受,這一行 LineChart 組件的調用也會非常的長。把這些屬性折行之后寫成 children,就可以更結構化地進行書寫。

為了改進類 html 語法的書寫體驗,我們在新語法里,增加了 # 的概念。

<LineChart :wdith="500" :height="300" :data="data"><attr #XAxis dataKey="name"/><attr #YAxis>true</attr><attr #CartesianGrid stroke="#eee" strokeDasharray="5 5"/>
</LineChart>

用 #xxx 的方式來表達,我是給組件傳遞了 xxx 屬性。這樣做為數據使用的 children,和做為組件使用的 children 就被區分開了。

給父組件傳遞 slot

#xxx 除了可以用來傳遞 attr 之外,也可以用來傳遞 slot。slot 分為三種:

  • UI fragment:例如一個 card 組件有一個 title 區域是可以自定義的。那么可以定義一個名為 title 的 slot,允許使用者傳入自己的實現。
  • 會被多次實例化的 template:例如一個 ListView 的每個 ListItem 是可用戶自定義的。但是和 card 組件的 title 不同,這里需要用戶傳入一個“函數”,因為每一行的數據是不一樣的。
  • 虛擬節點:微信小程序有一個概念叫虛擬節點。其實是上面所說的 template 的弱化形式。用戶傳入的是一個“組件名稱”,而不是一個“函數”。然后根據傳入的組件名字,會多次實例化該組件,達到用戶自定義的目的。

我們先來看 UI fragment 形式的表達方式:

定義組件
<div class="container"><header><slot :render="header" /></header><main><slot :render="children" /></main><footer><slot :render="footer" /></footer>
</div>

通過 <slot> 來表達,這個地方可以用戶自定義。

使用組件
<BaseLayout><fragment #header><h1>Here might be a page title</h1></fragment><fragment #children><p>A paragraph for the main content.</p><p>And another one.</p></fragment><fragment #footer><p>Here's some contact info</p></fragment>
</BaseLayout>

這里用 <fragment> 來表達,傳入的是一個具體的實例,而不是可以被多次調用的參數。如果是 React,那么類型就是 ReactNode。

第二種就是傳入可被多次實例化的 template

定義組件
<div class="container"><header><slot :render="header" title="abc" /></header><footer><slot :render="footer" title="xyz" /></footer>
</div>

<slot> 渲染的額時候,額外提供了參數

使用組件
<BaseLayout><template #header><h1>Here might be a page title: {{ #header.title }}</h1></template><template #footer><p>Here's some contact info: {{ #footer.title }}</p></template>
</BaseLayout>

傳入 template 和 fragment 不同,template 會捕獲參數,從而可以在 template 內容里引用。template 比 fragment 更常用,所以有一種簡寫形式:

使用組件
<BaseLayout><h1 #header>Here might be a page title: {{ #header.title }}</h1><p #footer>Here's some contact info: {{ #footer.title }}</p>
</BaseLayout>

綜上 #xxx 是一種傳遞各種復雜屬性的寫法。相比 jsx 的語法,折行書寫更舒服。

引用組件

vue 沒有在頁面模板里寫 import 的語法。最初 vue 是假設所有組件全局可引用的。而我們希望組件必須 import 了才可以使用,這樣就方便引入第三方的組件。例如引用微信小程序原生語法書寫的組件:

<import from="@vant/weapp/tag/index" as="VantTag"/>
<template #default><view><VantTag /></view>
</template>

這里引用的 @vant/weapp 是外部第三方組件,通過 import 就可以直接被使用。import 后的組件可以當作“虛擬節點”傳遞出去使用。這個是微信小程序特有的概念:

<import from="@app/MyComps/MyHeader" />
<import from="@app/MyComps/MyFooter" />
<template #default><BaseLayout :header="<MyHeader/>" :footer="<MyFooter/>" />
</template>

BaseLayout 要聲明自己接受這么兩個抽象節點,所以要和普通的 slot 區分開來

<div class="container"><header><slot :component="header" title="abc" /></header><footer><slot :component="footer" title="xyz" /></footer>
</div>

區別就是 <slot :component ..> 代替了 <slot :render ...>。

和 jsx 一樣的習慣,如果是小寫開頭的組件,則是平臺 native 的組件。例如 <div> <view> 這些都是不用 import 可以直接使用的。

引用 children

如果組件只有一個 slot 要傳,那沒有必要給這個 slot 命名了。缺省的 slot 名字就叫 children

定義組件
<div class="container"><main><slot :render="children" /></main>
</div>
使用組件
<BaseLayout><p>A paragraph for the main content.</p><p>And another one.</p>
</BaseLayout>

這個實際上等價于

使用組件
<BaseLayout><fragment #children><p>A paragraph for the main content.</p><p>And another one.</p></fragment>
</BaseLayout>

也就是普通寫法下的子組件,其實是一個 fragment 類型的 slot。

用 slot 來實現分支和循環

有了 slot,就相當于有了回調函數。那么就可以把分支和循環變成內置組件的功能,而不是一種固定語法。比如內置一個叫 <dynamic> 的組件

<dynamic :visible="vip"><p>you are vip</p>
</dynamic>

分支

<dynamic :slot="userType"><fragment #vip><p>you are vip</p></fragment><fragment #normal><p>you are normal</p></fragment>
</dynamic>

循環

<template #default><ul><dynamic :expand="items" key="id"><MyItem #element></dynamic></ul>
</template>
<template #MyItem><span>{{ #MyItem.firstName }}</span><span>{{ #MyItem.lastName }}
</template>

核心區別

  • 展示和邏輯分離,分成兩個文件來寫。不允許在頁面模板里寫表達式
  • 改進 html 傳遞復雜屬性寫法不方便的問題,引入寫在 tag body 中的 #xxx 屬性
  • 把 slot 做為第一等的公民,映射到各種運行時平臺的三種 slot 類型
  • 以 slot 為基礎,用內置組件代替分支/循環的語法

語法很大程度上是口味問題。不是說這么寫一定就比 jsx,vue,wxml 要高級。只是多了一種選擇。如果你需要選擇一種面向設計師的序列化格式,或者需要支持代碼生成,可以考慮考慮上述的類 vue 語法。

總結

以上是生活随笔為你收集整理的vue 模板_简化版的 vue 页面模板语法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。