zoukankan      html  css  js  c++  java
  • 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好,而是在需要的地方两者结合使用,效果会更好。

    不积跬步无以至千里
  • 相关阅读:
    Python零基础入门的基础案例
    今天不抠图,Python实现一键换底片!想换什么换什么(附源码)
    python基础:如何使用 pip 安装第三方库
    Python教程:matplotlib 绘制双Y轴曲线图
    福利来啦,送给大家一个小游戏的源码,不要错过哟
    招聘信息太多,哪家职位才是适合你的?Python采集招聘信息
    我的python菜鸟之路1
    我的SAS菜鸟之路3
    我的SAS菜鸟之路2
    猪鹿蝶1
  • 原文地址:https://www.cnblogs.com/lyt0207/p/13025923.html
Copyright © 2011-2022 走看看