Vue中渲染函數的使用
- 1. render函數
- 2. h()的使用
- 3. render函數和h函數的區分
- vue中的渲染函數:
- 1.
template
- 2.
render函數
- 3.
jsx -> js extension
(jsx
也是編譯成render函數
,可編程能力更強
)
- 1.
1. render函數
-
1.1. 認識h函數
- 1.1.1. Vue推薦在絕大多數情況下使用模板來創建HTML,一些特殊的場景,真的需要javaScript的完全編程的能力,
這個時候可以使用渲染函數,它比模板更接近編譯器。 - 1.1.2.
VNode
和VDom
的概念-
Vue在生成
真實DOM
之前,會將我們的節點轉換成VNode, 而VNode組合在一起形成一棵樹結構
,就是虛擬DOM(VDOM)
; -
事實上,之前編寫的
template中的HTML
最終也是使用渲染函數生成對應的VNode
; -
如果想重復利用
JavaScript的編程能力
,可以編寫createVNode函數,生成對應的VNode
; -
Vue底層渲染流程如下圖:
<!-- HTML模板 --> <!-- h函數 --> <!-- 虛擬節點VNode --> <!-- 真實DOM --> <template> <div> createVNode() VNode 真實DOM<h2></h2> createVNode() ↙ ↘ ↙ ↘ <p></p> createVNode() VNode VNode h2 p </div> </template>
-
- 1.1.1. Vue推薦在絕大多數情況下使用模板來創建HTML,一些特殊的場景,真的需要javaScript的完全編程的能力,
-
1.2. 使用h函數
- h() 函數是一個用于創建vnode的一個函數;
- 其實更準確的命名是createVNode()函數,但是為了簡便在Vue將之簡化為h()函數(本質上是createVNode()函數)
2. h()的使用
- h()函數接收三個參數:tag, props, children
{ String | Object | Function } tag { Object } props { String | Array | Object } children一個HTML標簽、一個組件、一個異步組件、或 與attribute、prop 和事件相對應的對象 子 VNodes, 使用`h()` 構建一個函數式組件 會在模板中使用 使用字符串獲取 `文本 VNode`或`有插槽的對象`必需的 可選的 可選的例如:'div' { } [ 'some text comes first',h('h1', null, '哈哈哈哈'),h(myComponent, {someProp: 'fooBar'})]
- 注意事項:
- 如果沒有props, 通常可以將children作為第二個參數傳入;
- 如果會產生歧義,可以將null作為第二個參數傳入,將children作為第三個參數傳入;
- HTML轉成VNode的調用案例:
<div class="abc" title='內容'>h2p</div>// 轉成VNode:createVNode('div', { class: 'abc', title: '內容' }, [createVNode('h2', null, '我是標題'),createVNode('p', { }, '我是內容')])
- createVNode函數的調用如下圖;
3. render函數和h函數的區分
-
流程:render函數是放在對應的組件選項里面的,當渲染組件的時候,會調用render函數,一旦調用就會返回的VNode,為了去創建一系列的VNode, 所以會調用h函數并渲染成HTML
-
區分:render函數是寫到組件里面的,而h函數(createVNode函數)才是真正去創建VNode的
-
- render函數使用
-
Options API
的用法,使用render函數選項
- 代碼如下:
<script>import { h } from 'vue'import Home from './Home.vue'export default {data () {return {counter: 0}},render () {console.log('this===', this);return h('div', { class: 'app' } , [h('h2', { class: 'title' }, `當前計數:${ this.counter }`),h('button', { onClick: this.increment }, '+1'),h('button', { onClick: this.decrement }, '-1'),// 在render函數中,引入其他組件不需要注冊(components), 在template模板中需要注冊h(Home)])},methods: {increment () {this.counter++},decrement() {this.counter--}}}</script>
-
Composition API
的用法
- 2.1.
setup函數
的使用,- 關鍵點:
setup()
中返回一個函數,函數中返回VNode setup函數
默認返回一個對象=>
return { counter, increment, decrement }
setup函數
中使用render函數
,不要返回對象,setup本身需要是返回一個函數類型, 箭頭函數中再去返回VNode
- 代碼如如下:
<script>import { h, ref } from 'vue'import Home from './Home.vue'export default {setup () {const counter = ref(0)const increment = () => {counter.value++}const decrement = () => {counter.value--}// setup函數默認返回一個對象 => return { counter, increment, decrement }// setup函數中使用render函數,不要返回對象,返回一個函數, 箭頭函數中再去返回VNodereturn () => {return h('div', {className: 'app' }, [h('h2', { className: 'title' }, `當前計數: ${ counter.value }`),h('button', { onClick: increment }, '+1'),h('button', { onClick: decrement} , '-1'),h(Home)])}// return () => h('div', {className: 'app' }, [// h('h2', { className: 'title' }, `當前計數: ${ counter.value }`),// h('button', { onClick: increment }, '+1'),// h('button', { onClick: decrement} , '-1'),// h(Home)// ])}}</script>
- 關鍵點:
- 2.2.
setup語法糖
的使用- 在setup中義render函數
- 在template模板中使用render標簽
- 代碼如下;
<template><render/></template><script setup>import { ref, h } from 'vue'import Home from './Home.vue'const counter = ref(0)const increment = () => {counter.value++}const decrement = () => {counter.value--}// 使用render函數,是為了使用js的方式去編寫代碼,基本上很少使用// 如果依然想使用JS的方式編寫,可以使用JSX語法,JSX本質會轉化成render函數// JSX的優點:1. 快速的編寫元素的結構 2. 完全可以利用JS編程能力const render = () => h('div', {className: 'app' }, [h('h2', { className: 'title' }, `當前計數: ${ counter.value }`),h('button', { onClick: increment }, '+1'),h('button', { onClick: decrement} , '-1'),h(Home)])</script>
-
- render函數的使用推薦
- 使用render函數,是為了使用js的方式去編寫代碼,
基本上很少使用
- 如果依然想使用JS的方式編寫,可以使用JSX語法,JSX本質會轉化成render函數
JSX的優點
:-
- 快速的編寫元素的結構
-
- 完全可以利用JS編程能力
-