render函数demo

用render函数的好处是复杂的逻辑不利于template的维护,此时可以用到render函数。
render函数demo渲染的效果图
在这里插入图片描述
demo目录结构
在这里插入图片描述

App.vue

<template>
  <div id="app">
       <keep-alive :include="cached" exclude="ACompoment" :max="99">
          <LifeCycle  v-if="isExist" v-model="isExist" @close="doClose" ></LifeCycle>
       </keep-alive>
    <component :is="dynamicName" />
    <div>名字切换</div>
<!--    <select v-model="dynamicName" name="" id="">-->
<!--    <option v-for="(name,index) in compsName" :key="index" :value="name">{{ name }}</option>-->
<!--  </select>-->
    <hr>
    组件切换
    <select @change="toggleName" name="" id="">
    <option v-for="(name,index) in compsName" :key="index" :value="name">{{ name }}</option>
  </select>
      <render-box/>
      <jsx-box/>
      <hr>

      <LowCode/>
  </div>
</template>

<script>
  import LifeCycle from './components/LifeCycle.vue'
  import BComp from "./components/BCompoment";
  import AComp from "./components/ACompoment";
  import CComp from "./components/CCompoment";
  import RenderBox from './components/RenderBox';
  import JsxBox from './components/JsxBox';
  import LowCode from './components/LowCode.vue'

  export default {
  name: 'App',
  components: { LifeCycle, BComp, AComp, CComp,RenderBox,JsxBox,LowCode},
  data(){
    return{
      compsName:['AComp','BComp','CComp'],
      isExist:true,
      cached: [
        'MyLifeCycle'
      ],
      dynamicName: 'BComp',
    }
  },
  methods:{
    doClose(url){
      this.cached.splice(this.cached.indexOf(url), 1);
    },
    toggleName(e){
      console.log('切换到了,', e.target.value);
      switch(e.target.value){
        case 'AComp':
          return this.dynamicName=AComp;
        case 'BComp':
          return this.dynamicName = {
            name:'BComp',
            ...BComp,
          }
          case 'CComp':
            return this.dynamicName={
                name:'CComp',
                render:CComp.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>
	

初级版
RenderBox.vue
直接用render函数渲染

<script>
export default {
   methods:{
     getDomAttr(){
         return { style: { background: 'pink' ,border:'1px solid #555'}, attrs: { mytest: 'abc' }, on: { click: function () { alert(1) } } };
     }
   },
  render(h){
// 组件或者标签名
    return h('div', this.getDomAttr(), [
      h('h2', {}, '1'),
      h('h2', {}, '2'),
      h('h2', {}, '3'),
    ]);
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

中级版
JsxBox.vue
用jsx的语法,可以用html标签,也可以用纯函数做复杂的逻辑判断。

<script>
    // 纯函数, 不依赖于函数上下文
    // 纯函数: 不依赖this相关的属性,通过形参的传递,来实现功能
    function renderDemo1(h,num1) {
        return num1 === 1 && <div>111</div>
    }
    function renderDemo(h,num, num1) {
        switch (num) {
            case 1:
                return <div>一的内容  {renderDemo1(h,num1)}   </div>;
            case 2:
                return <div>二的内容</div>
        }
    }
    // function renderForm(h,form){
    //     // 使用v-model需要组件this支撑
    //     return <input v-model={ form.username } />
    // }
    // function renderForm(h,form){
    //     // 使用v-model需要组件this支撑
    //     return <input value={ form.username } onInput={ val => form.username = val.target.value }  />
    // }
export default {
   methods:{
       doClick() {
           console.log('开始点击了...')
       },
       // renderTest() {
       //     return (
       //         <div style={{ background: 'yellow' }} test={'abc'} onClick={this.doClick}  >
       //         <h2>11</h2>
       //         <h2>22</h2>
       //         <h2>33</h2>
       //         </div>
       // )
       // },
       // renderDemo(h, num1) {
       //     return this.num === 1 ? <div>一的内容  {renderDemo1(h, num1)}   </div> : this.num === 2 ? <div>二的内容</div> : null
       // },

   },
    data() {
        return {
            num: 1,
            num1: 1,
            form:{ username:'哈哈'  }
        }
    },
  render(h){
      const { num1 } = this;
      return renderDemo(h, num1);
       // return this.renderDemo(h, num1);
      // return renderForm.call(this,h,form);
     // return renderForm(h,form)
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

高级版
LowCode.vue
低代码demo 应用render函数
把左边的a,b,c 组件拖入右边的灰色框里面;

<template>
   <div class="box">
       <div class="aside">
           <!-- vue-draggable -->
           <button compName="AComp" draggable="true" @dragstart="recordData">A组件</button>
           <button compName="BComp" draggable="true" @dragstart="recordData">B组件</button>
           <button compName="CComp" draggable="true" @dragstart="recordData">C组件</button>
       </div>
       <div class="viewport" @dragover.prevent @drop="addComp">
           <div :id="item.id" v-for="(item,index) in comps" :key="index"></div>
       </div>
   </div>
</template>

<script>
    import BComp from "./BCompoment";
    import AComp from "./ACompoment";
    import CComp from "./CCompoment";
    import Vue from 'vue';
    export default {
        components:{
            BComp,AComp,CComp
        },
        data(){
            return {
                comps: []
            }
        },
        methods:{
            addComp(e){
                let compName = e.dataTransfer.getData('compName');
                console.log('组件名称:', compName);
                const Comp = this.$options.components[compName];
                //添加一个坑
                this.comps.push({
                    id: compName
                })
                this.$nextTick(()=>{
                   //2.触发渲染 render
                     new Vue({
                         render:Comp.render,
                     }).$mount('#'+compName)
                })

            },
            recordData(e) {
                console.log('开始拖动了',e)
                let compName = e.target.getAttribute('compName');
                e.dataTransfer.setData('compName', compName);
            }
        }
    }
</script>
<style scoped>
    .box {
        width: 1000px;
        display: flex;
    }

    .box,
    .aside,
    .viewport {
        height: 800px;
    }

    .aside {
        width: 300px;
        background: yellowgreen;
    }

    .viewport {
        flex: 1;
        background: grey;
    }
</style>

A 组件
B 组件
C 组件

<template>
  <div>
    我是A组件
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
Logo

前往低代码交流专区

更多推荐