教練,怎么在vue項(xiàng)目里寫(xiě)react?
1.前言
我承認(rèn)了我是標(biāo)題黨,本篇文章是在vue項(xiàng)目里寫(xiě)tsx的一篇介紹。作為一個(gè)reacter,目前的業(yè)務(wù)天天使用vue2+ts讓我十分的不舒服。我對(duì)于vue也不是很熟悉,想回到我的react時(shí)代。于是在查詢(xún)官網(wǎng)之后發(fā)現(xiàn)在vue里面寫(xiě)jsx也挺有意思的,遂記錄。
2.正文
vue2+ts的項(xiàng)目配置這里就不展開(kāi)了,網(wǎng)上一搜一大推。
index.vue是頁(yè)面路由,存放各個(gè)組件和公用邏輯。components文件夾中存放我的tsx組件。
接下來(lái)就開(kāi)始寫(xiě)tsx。
你可以直接創(chuàng)建jsx/tsx文件
這次的項(xiàng)目結(jié)構(gòu)是這樣的:
在vue文件里這么使用
- // index.vue
- <template>
- <div class="wrapper">
- <Common :opt="list" />
- </div>
- </template>
- <script lang="ts">
- import { Component, Vue } from "vue-property-decorator";
- import Common from "./components/Common";
- @Component({
- name: "App",
- components: {
- Common,
- },
- })
- export default class App extends Vue {
- private list = ["我要去淘寶", "我要去百度", "我要去京東"];
- }
- </script>
tsx這么寫(xiě)
- import { CreateElement } from 'vue';
- import { Component, Vue, Prop } from 'vue-property-decorator';
- @Component({
- name: 'Common'
- })
- export default class Common extends Vue {
- @Prop(Object) opt!: any[]
- render(h: CreateElement) {
- return <span>
- {
- this.opt.map((it) => {
- return <span style="marginRight:10px">{it}</span>
- })
- }
- </span>
- }
- }
在來(lái)看一下頁(yè)面
這該死的react既視感,竟是如此的誘人
可能有心者注意到了 我還引用了一個(gè) CreateElement
,這是干嘛的呢。這玩意叫 渲染函數(shù)
。不喜歡讀vue那么大串的文檔的兄弟看這里。簡(jiǎn)單解釋?zhuān)哼@個(gè)東西可以渲染一個(gè)vnode節(jié)點(diǎn)。 它比模板更接近編譯器。
什么意思呢?意思就是模板語(yǔ)法也會(huì)編譯成渲染函數(shù)。所以我們直接用渲染函數(shù)不就相當(dāng)于節(jié)省了模板語(yǔ)法到渲染函數(shù)的過(guò)程。四舍五入項(xiàng)目性能又是一個(gè)大的提升!
簡(jiǎn)單介紹一下傳參:
第一個(gè)參數(shù)
: {String | Object | Function} 一個(gè) HTML 標(biāo)簽名、組件選項(xiàng)對(duì)象,或者 resolve 了上述任何一種的一個(gè) async 函數(shù)。必填項(xiàng)。
第二個(gè)參數(shù)
: Object 一個(gè)與模板中 attribute 對(duì)應(yīng)的數(shù)據(jù)對(duì)象。
第三個(gè)參數(shù)
: {String | Array} 文本節(jié)點(diǎn)或子級(jí)虛擬節(jié)點(diǎn) (VNodes)。
渲染函數(shù)給vue帶來(lái)了很多的靈活性,以前你想自定義在子組件里插入東西,得寫(xiě)一大堆的插槽。 <slot>
。有了渲染函數(shù)我們可以這么玩。
- // 改造一下上面的index.vue的data
- private list = [
- { render: () => ["a", { style: { color: "red" } }, "我要去淘寶"] },
- { render: () => ["a", { style: { color: "green" } }, "我要去京東"] },
- { render: () => ["a", { style: { color: "pink" } }, "我要去百度"] },
- ];
tsx中這么寫(xiě):
- {
- this.opt.map((it) => {
- return h(...it.render())
- })
- }
就可以渲染出花里胡哨的頁(yè)面了
我們還可以這么玩:
- // tsx改造
- <span>
- {
- this.opt.map((it) => {
- return it.render(h)
- })
- }
- </span>
- 在index.vue頁(yè)面我們就可以這么玩:
- // index.vue
- private list = [
- {
- render: (h: CreateElement) =>
- h("a", { style: { color: "red", marginRight: "5px" } }, "我要去淘寶"),
- },
- {
- render: (h: CreateElement) =>
- h("a", { style: { color: "green", marginRight: "5px" } }, "我要去京東"),
- },
- {
- render: (h: CreateElement) =>
- h("a", { style: { color: "pink", marginRight: "5px" } }, "我要去百度"),
- },
- ];
結(jié)果也是同樣的花哨
我們同樣可以渲染亂七八糟的標(biāo)簽!
- // index.vue改造
- {
- render: (h: CreateElement) =>
- h(
- "h1",
- {
- style: { color: "green", marginRight: "5px" },
- },
- "我要去京東"
- ),
- },
我們可以隨心所欲的在渲染函數(shù)中定義事件:
- // index.vue
- private list = [
- {
- render: (h: CreateElement) =>
- h(
- "a",
- {
- style: { color: "red", marginRight: "5px" },
- on: {
- click: () => this.iWillGoWhere("TB"),
- },
- },
- "我要去淘寶"
- ),
- }]
- iWillGoWhere(type: string) {
- const goWhere: any = {
- TB: () => {
- alert("我要去淘寶!");
- },
- JD: () => {
- alert("我要去京東!");
- },
- BD: () => {
- alert("我要去百度!");
- },
- };
- goWhere[type]();
- }
這樣就可以啦!
結(jié)尾
本次文章是對(duì)vue靈活性使用的入門(mén)。請(qǐng)各位vue大佬不要噴我~