Vue中的template 里面使用的模版是HTML語(yǔ)法組件的頁(yè)面,在Vue中都會(huì)被編譯成render函數(shù)吼过,Vue會(huì)采用虛擬dom進(jìn)行頁(yè)面組件渲染。
render函數(shù)基本使用
render不能與template 一起使用,否則無(wú)效梯捕。
<script>
export default {
name:'render',
render(createElement){
return createElement('h1',{},'hello')
}
}
</script>
在APP.vue中引入Render.vue
<template>
<div id="app">
<Render></Render>
</div>
</template>
<script>
import Render from './components/Render'
export default {
name: 'App',
components: {
Render
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
通過(guò)render動(dòng)態(tài)渲染節(jié)點(diǎn) Render.vue 修改為
<script>
export default {
name:'render',
props:{
tag:{
type:String,
required:true,
},
data:{
type:String
}
},
render(createElement){
return createElement(this.tag,{},this.data)
}
}
</script>
App.Vue 中使用 :tag :data 傳參
<template>
<div id="app">
<Render :tag="'div'" :data="'Hello World!'" ></Render>
</div>
</template>
createElement 第二個(gè)參數(shù)可以設(shè)置屬性
render(createElement){
return createElement(this.tag,{
class:'render-color'
},this.data)
}
<style scoped>
.render-color{
background-color: aqua;
}
</style>
也可以使用 domProps 進(jìn)行設(shè)置
render(createElement){
return createElement(this.tag,{
// class:'render-color',
domProps:{
className:'render-color',
innerHTML:'hahhaha', // 會(huì)替換傳進(jìn)來(lái)的data的值
}
},this.data)
}
createElement 第三個(gè)參數(shù)可以傳一個(gè)數(shù)組匙瘪,從而實(shí)現(xiàn)嵌套
render(createElement){
return createElement(this.tag,{
class:'render-color',
},[createElement('p',{},'balabal')])
}
createElement 簡(jiǎn)易版
- 創(chuàng)建一個(gè)createElement
function Element(type,props,children){
this.type = type
this.props = props
this.children = children
}
function createElement(type,props,children){
return new Element(type,props,children)
}
- 實(shí)現(xiàn)render 函數(shù)
function render(obj){
// 創(chuàng)建節(jié)點(diǎn)
let el = document.createElement(obj.type)
for (let key in obj.props){
el.setAttribute(key,obj.props[key])
}
if(Array.isArray(obj.children)){
obj.children.forEach(element => {
// 遞歸操作铆铆,如果當(dāng)前child不是文本,就繼續(xù)進(jìn)行操作丹喻,否則創(chuàng)建文本節(jié)點(diǎn)
element = element instanceof Element? render(element):document.createTextNode()
el.appendChild(element)
});
}
else if (typeof obj.children === 'string'){ // 如果是字符串當(dāng)成數(shù)組進(jìn)行遞歸
el.appendChild(document.createTextNode(obj.children))
}
return el
}
完整代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
<script>
let myDom = createElement('div',{class:'container',style:'color:red'},
[
createElement('p',{class:'item'},'child1'),
createElement('p',{class:'item'},'child2'),
createElement('p',{class:'item'},'child3'),
createElement('input',{class:'item',value:'I am input'},'child4')
])
let myDom2 = createElement('p',{class:'item'},'child23233')
function Element(type,props,children){
this.type = type
this.props = props
this.children = children
}
function createElement(type,props,children){
return new Element(type,props,children)
}
function render(obj){
// 創(chuàng)建節(jié)點(diǎn)
let el = document.createElement(obj.type)
for (let key in obj.props){
el.setAttribute(key,obj.props[key])
}
if(Array.isArray(obj.children)){
obj.children.forEach(element => {
// 遞歸操作薄货,如果當(dāng)前child不是文本,就繼續(xù)進(jìn)行操作碍论,否則創(chuàng)建文本節(jié)點(diǎn)
element = element instanceof Element? render(element):document.createTextNode()
el.appendChild(element)
});
}
else if (typeof obj.children === 'string'){ // 如果是字符串當(dāng)成數(shù)組進(jìn)行遞歸
el.appendChild(document.createTextNode(obj.children))
}
return el
}
function renderDom(node,target){
node.appendChild(target)
}
let node2 = render(myDom2)
let app = document.getElementById('app')
renderDom(app,render(myDom))
renderDom(app,render(myDom2))
</script>
</html>
<style>
.container{
font-weight: 700;
}
.item{
background-color: darkolivegreen;
}
</style>