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