Vue render 函數和JSX語法的使用


基本使用

Vue 推薦在絕大多數情況下使用模板來創建你的 HTML。然而在一些場景中,你真的需要 JavaScript 的完全編程的能力。這時你可以用渲染函數,它比模板更接近編譯器。

讓我們深入一個簡單的例子,這個例子里 render 函數很實用。假設我們要根據父組件傳過來的數據決定顯示哪個標簽:

父組件:

<template>
  <div id="app">
    <level type="1">hello world</level>
    <level type="2">hello world</level>
    <level type="3">hello world</level>
    <level type="4">hello world</level>
  </div>
</template>

<script> import Level from './components/Level' export default { name: 'App', components: { Level } } </script>

Level組件:

<template>
    <div>
        <h1 v-if="type == 1"><slot></slot></h1>
        <h2 v-else-if="type == 2"><slot></slot></h2>
        <h3 v-else-if="type == 3"><slot></slot></h3>
        <h4 v-else-if="type == 4"><slot></slot></h4>
    </div>
</template>
<script> export default { name: 'Level', props:{ type: String || Number } } </script>

Level組件根據父組件穿過來的type來判斷顯示h1、h2、h3等標簽,v-if 可以說用到了"極致",而且寫了很多個冗余的slot

使用render函數和JSX語法來改寫上面

Level.js文件

export default { props:{ type: String | Number }, methods:{ handleClick(e){ console.log(e.target) }, }, data(){ return {msg:'zf'} }, render(h){ //運行時
        // h('h' + this.type,{},[this.$slots.default])
        let tag = 'h' + this.type return <tag>
            <span value={tag} onClick={this.handleClick}>{this.$slots.default}</span>
            {this.msg} </tag>
 } }

省去了很多冗余代碼,頁面一下清爽了很多

用JSX語法實現v-model、v-if、v-for語法

v-model:

export default { methods:{ handleInput(e){ this.msg = e.target.value } }, data(){ return {msg:'zf'} }, render(){ //運行時return {/* 實現v-model */} <input type="text" value={ this.msg} onInput={this.handleInput}></input>
            {this.msg} } }

給input框頂一個value屬性 一個input事件onInput,傳值和監聽事件改變值。

v-if: 三元表達式

render(){ return ( <div> {this.show?'好':'不好'} </div>
 ) }

簡單的語法可以用三元表達式

復雜的語法還是要用if/else來判斷

render(){ let ifText if(this.show){ ifText=<p>好</p>
        }else { ifText=<p>不好</p>
 } return ( <div> {ifText} </div>
 ) }

v-for:以menu菜單為例

import elMenu from "./el-menu"; import elMenuItem from "./el-menu-item"; import elSubmenu from "./el-submenu"; export default { //父組件傳過來的數據
 props:{ data:{ type: Array, default:() => {} } }, data(){ return { menudata:[ {title: '根1', id: 1}, {title: '根2', id: 2, children: [ { title:'根2-1', id: 21, children: [ {title: '根2-1-1', id: 211}, {title: '根2-1-2', id: 212} ] } ] }, {title: '根3', id: 3}, {title: '根4', id: 4,children: [ {title: '根4-1', id: 41} ]} ] } }, render() { let renderChildren = (data) => { return data.map(child =>{ return child.children ? //判斷是否有孩子
                //有孩子渲染elSubmenu
                <elSubmenu> 
                    <div slot="title">{child.title}</div>
 {renderChildren(child.renderChildren)} </elSubmenu> : //沒有孩子渲染elMenuItem
                <elMenuItem></elMenuItem>
 }) } return <elMenu> {/* 循環遍歷孩子 顯示哪一個 */} {renderChildren(this.data)} </elMenu>
 } }

 用自定義組件

導入進來,不用再在components屬性聲明了,直接寫在jsx中

<script> import HelloWolrd from './HelloWorld' export default { name: "item", render(){ return ( <HelloWolrd/>
 ) } } </script>

事件,class,style,ref等的綁定方式

render (h) { return ( <div // normal attributes or component props.
   id="foo"
   // DOM properties are prefixed with `domProps`
   domPropsInnerHTML="bar"
   // event listeners are prefixed with `on` or `nativeOn`
   onClick={this.clickHandler} nativeOnClick={this.nativeClickHandler} // other special top-level properties
   class={{ foo: true, bar: false }} style={{ color: 'red', fontSize: '14px' }} key="key" ref="ref"
   // assign the `ref` is used on elements/components with v-for
 refInFor slot="slot">
  </div>
 ) }

上面有個地方需要注意,當給自定義組件綁定事件時用nativeOnClick,而模板格式是用@click.native

 在實際開發中並不是全部都有renderJSX語法好或者全都用template好,而是在需要的地方兩者結合使用,效果會更好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM