學(xué)習(xí)JSX,先了解一下createElement
提到JSX,不可避免的就要提到createElement,當(dāng)你看完本節(jié),你會發(fā)現(xiàn),奇怪的知識又增多了。ok,我們接著上一部分繼續(xù)講。這一次的準(zhǔn)備工作是了解createElement。
從Vue編譯后的代碼看createElement
你是否看過寫的Vue代碼經(jīng)過編譯之后的樣子,比如下面這段代碼
<template>
<div>我喜歡<span class="emphasize">前端</span></div>
</template>
小編對這段代碼進(jìn)行編譯之后,得到下面這段代碼
function () {
var e = this,
// e._self._c 對應(yīng)源碼里面的createElement
t = e._self._c;
// 返回了一個 createElement('div',[])
return t("div", [
// e._v 對應(yīng)源碼里面的createTextVNode
e._v("my"),
t("span", { staticClass: "emphasize" }, [e._v("前端")]),
]);
}
通過對上面的代碼進(jìn)行分析,不難發(fā)現(xiàn),Vue模板中的每一個元素編譯之后都會對應(yīng)一個createElement,那么這個createElement到底是什么,嗯,這個你面試的時候也許已經(jīng)提到過了。
那么什么是createElement
無論是Vue還是React,都存在createElement,而且作用基本一致。可能你對createElement不是很了解,函數(shù)名翻譯過來就是增加一個元素,但他的返回值你一定知道。createElement函數(shù)返回的值稱之為虛擬節(jié)點,即VNode,而由VNode扎堆組成的樹便是大名鼎鼎,面試必問的虛擬DOM。
createElement函數(shù)的參數(shù),在這里小編偷個懶抄一下Vue官方文檔
// @returns {VNode}
createElement(
// {String | Object | Function}
// 一個 HTML 標(biāo)簽名、組件選項對象,或者
// resolve 了上述任何一種的一個 async 函數(shù)。必填項。
'div',
// {Object}
// 一個與模板中 attribute 對應(yīng)的數(shù)據(jù)對象??蛇x。
{
// (詳情見下一節(jié))
},
// {String | Array}
// 子級虛擬節(jié)點 (VNodes),由 `createElement()` 構(gòu)建而成,
// 也可以使用字符串來生成“文本虛擬節(jié)點”??蛇x。
[
'先寫一些文字',
createElement('h1', '一則頭條'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
從上面可以看出createElement一共有三個參數(shù),三個參數(shù)分別是
- 第一個參數(shù)是需要渲染的組件,可以是組件的標(biāo)簽,比如
div;或者是一個組件對象,也就是你天天寫的export default {};亦或者可以是一個異步函數(shù)。 - 第二個參數(shù)是這個組件的屬性,是一個對象,如果組件沒有參數(shù),可以傳null(關(guān)于組件的屬性,下文將依次介紹)
- 第三個參數(shù)是這個組件的子組件,可以是一個字符串(textContent)或者一個由VNodes組成的數(shù)組
用createElement寫一個組件吧
表單示例
假設(shè)我們需要開發(fā)一個下面這樣的表格(element-ui的)
用模板代碼去開發(fā)
如果我們用模板代碼去開發(fā)這個表單,那么代碼大概就長這樣
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="審批人">
<el-input v-model="formInline.user" placeholder="審批人"></el-input>
</el-form-item>
<el-form-item label="活動區(qū)域">
<el-select v-model="formInline.region" placeholder="活動區(qū)域">
<el-option label="區(qū)域一" value="shanghai"></el-option>
<el-option label="區(qū)域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查詢</el-button>
</el-form-item>
</el-form>
用createElement去實現(xiàn)
如果我們直接將上面的代碼轉(zhuǎn)換為用createElement去實現(xiàn),那么代碼將會是這樣的
export default {
methods: {
$_handleChangeUser(value) {
this.formInline.user = value
}
},
render(createElement) {
return createElement(
'ElForm',
{
props: {
inline: true,
model: this.formInline
},
staticClass: 'demo-form-inline'
},
[
createElement(
'ElFormItem',
{
props: {
label: '審批人'
}
},
[
createElement('ElInput', {
props: {
value: this.formInline.user
},
attrs: {
placeholder: '審批人'
},
on: {
input: this.$_handleChangeUser
}
})
]
),
createElement(
'ElFormItem',
{
props: {
label: '活動區(qū)域'
}
},
[
createElement(
'ElSelect',
{
props: {
value: this.formInline.region,
placeholder: '活動區(qū)域'
}
},
[
createElement('ElOption', {
props: {
label: '區(qū)域一',
value: 'shanghai'
}
}),
createElement('ElOption', {
props: {
label: '區(qū)域二',
value: 'beijing'
}
})
]
)
]
),
createElement('ElFormItem', null, [
createElement(
'ElButton',
{
props: {
type: 'primary'
},
on: {
click: this.$_handleSubmit
}
},
'查詢'
)
])
]
)
}
}
看到上面的代碼,你可能會驚呼,代碼好多啊,好痛苦,想當(dāng)年發(fā)明JSX的人剛開始天天也是寫createElement,寫的直掉頭發(fā),太痛苦了,然后就使勁撓頭,當(dāng)額頭锃光發(fā)亮的時候,終于想到了一種新的語法,就是JSX。從此之后,頭發(fā)呼呼的又長回來了。
看到上面代碼,你會發(fā)現(xiàn)有一個render函數(shù),這個函數(shù)叫做渲染函數(shù),相當(dāng)于通過createElement或JSX去實現(xiàn)功能的主入口方法。而且你熟悉的v-model也沒見了,而是用value + input代替了。
ok,這一部分先寫到這里,下一篇文章寫下一部分:是時候使用JSX代替createElement了。喜歡的朋友可以繼續(xù)看哦,我更新非??炫?。也會一直出優(yōu)秀的文章給大家分享。