zoukankan      html  css  js  c++  java
  • vue render

    官网描述的场景当我们开始写一个通过 level prop 动态生成 heading 标签的组件,你可能很快想到这样实现:

    <script type="text/x-template" id="anchored-heading-template">
     <h1 v-if="level === 1">
      <slot></slot>
     </h1>
     <h2 v-else-if="level === 2">
      <slot></slot>
     </h2>
     <h3 v-else-if="level === 3">
      <slot></slot>
     </h3>
     <h4 v-else-if="level === 4">
      <slot></slot>
     </h4>
     <h5 v-else-if="level === 5">
      <slot></slot>
     </h5>
     <h6 v-else-if="level === 6">
      <slot></slot>
     </h6>
    </script>
    Vue.component('anchored-heading', {
     template: '#anchored-heading-template',
     props: {
      level: {
       type: Number,
       required: true
      }
     }
    })

    在这种场景中使用 template 并不是最好的选择:首先代码冗长,为了在不同级别的标题中插入锚点元素,我们需要重复地使用 <slot></slot>。

    虽然模板在大多数组件中都非常好用,但是在这里它就不是很简洁的了。那么,我们来尝试使用 render 函数重写上面的例子:

    Vue.component('anchored-heading', {
     render: function (createElement) {
      return createElement(
       'h' + this.level,  // tag name 标签名称
       this.$slots.default // 子组件中的阵列
      )
     },
     props: {
      level: {
       type: Number,
       required: true
      }
     }
    })

    简单清晰很多!简单来说,这样代码精简很多,但是需要非常熟悉 Vue 的实例属性。在这个例子中,你需要知道当你不使用 slot 属性向组件中传递内容时,比如 anchored-heading 中的 Hello world!,这些子元素被存储在组件实例中的 $slots.default中。

    createElement参数介绍

    接下来你需要熟悉的是如何在 createElement 函数中生成模板。这里是 createElement 接受的参数:

    createElement(
     // {String | Object | Function}
     // 一个 HTML 标签字符串,组件选项对象,或者
     // 解析上述任何一种的一个 async 异步函数,必要参数。
     'div',
    
     // {Object}
     // 一个包含模板相关属性的数据对象
     // 这样,您可以在 template 中使用这些属性。可选参数。
     {
      // (详情见下一节)
     },
    
     // {String | Array}
     // 子节点 (VNodes),由 `createElement()` 构建而成,
     // 或使用字符串来生成“文本节点”。可选参数。
     [
      '先写一些文字',
      createElement('h1', '一则头条'),
      createElement(MyComponent, {
       props: {
        someProp: 'foobar'
       }
      })
     ]
    )

    深入 data 对象

    有一件事要注意:正如在模板语法中,v-bind:class 和 v-bind:style ,会被特别对待一样,在 VNode 数据对象中,下列属性名是级别最高的字段。该对象也允许你绑定普通的 HTML 特性,就像 DOM 属性一样,比如 innerHTML (这会取代 v-html 指令)。

    {
     // 和`v-bind:class`一样的 API
     'class': {
      foo: true,
      bar: false
     },
     // 和`v-bind:style`一样的 API
     style: {
      color: 'red',
      fontSize: '14px'
     },
     // 正常的 HTML 特性
     attrs: {
      id: 'foo'
     },
     // 组件 props
     props: {
      myProp: 'bar'
     },
     // DOM 属性
     domProps: {
      innerHTML: 'baz'
     },
     // 事件监听器基于 `on`
     // 所以不再支持如 `v-on:keyup.enter` 修饰器
     // 需要手动匹配 keyCode。
     on: {
      click: this.clickHandler
     },
     // 仅对于组件,用于监听原生事件,而不是组件内部使用
     // `vm.$emit` 触发的事件。
     nativeOn: {
      click: this.nativeClickHandler
     },
     // 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
     // 赋值,因为 Vue 已经自动为你进行了同步。
     directives: [
      {
       name: 'my-custom-directive',
       value: '2',
       expression: '1 + 1',
       arg: 'foo',
       modifiers: {
        bar: true
       }
      }
     ],
     // Scoped slots in the form of
     // { name: props => VNode | Array<VNode> }
     scopedSlots: {
      default: props => createElement('span', props.text)
     },
     // 如果组件是其他组件的子组件,需为插槽指定名称
     slot: 'name-of-slot',
     // 其他特殊顶层属性
     key: 'myKey',
     ref: 'myRef'
    }

    条件渲染

    既然熟读以上api接下来咱们就来点实战。

    之前这样写

    //HTML
    <div id="app">
      <div v-if="isShow">我被你发现啦!!!</div>
    </div>
    <vv-isshow :show="isShow"></vv-isshow>
    //js
    //组件形式
    Vue.component('vv-isshow', {
      props:['show'],
      template:'<div v-if="show">我被你发现啦2!!!</div>',
    });
    var vm = new Vue({
      el: "#app",
      data: {
        isShow:true
      }
    });

    render这样写

    //HTML
    <div id="app">
      <vv-isshow :show="isShow"><slot>我被你发现啦3!!!</slot></vv-isshow>
    </div>
    //js
    //组件形式
    Vue.component('vv-isshow', {
      props:{
        show:{
          type: Boolean,
          default: true
        }
      },
      render:function(h){
        if(this.show ) return h('div',this.$slots.default);
      },
    });
    var vm = new Vue({
      el: "#app",
      data: {
        isShow:true
      }
    });

    列表渲染

    之前是这样写的,而且v-for 时template内必须被一个标签包裹

    //HTML
    <div id="app">
      <vv-aside v-bind:list="list"></vv-aside>
    </div>
    //js
    //组件形式
    Vue.component('vv-aside', {
      props:['list'],
      methods:{
        handelClick(item){
          console.log(item);
        }
      },
      template:'<div>
             <div v-for="item in list" @click="handelClick(item)" :class="{odd:item.odd}">{{item.txt}}</div>
           </div>',
      //template:'<div v-for="item in list" @click="handelClick(item)" :class="{odd:item.odd}">{{item.txt}}</div>',错误
    });
    var vm = new Vue({
      el: "#app",
      data: {
        list: [{
          id: 1,
          txt: 'javaScript',
          odd: true
        }, {
          id: 2,
          txt: 'Vue',
          odd: false
        }, {
          id: 3,
          txt: 'React',
          odd: true
        }]
      }
    });

    render这样写

    //HTML
    <div id="app">
      <vv-aside v-bind:list="list"></vv-aside>
    </div>
    //js
    //侧边栏
    Vue.component('vv-aside', {
      render: function(h) {
        var _this = this,
          ayy = this.list.map((v) => {
            return h('div', {
              'class': {
                odd: v.odd
              },
              attrs: {
                title: v.txt
              },
              on: {
                click: function() {
                  return _this.handelClick(v);
                }
              }
            }, v.txt);
          });
        return h('div', ayy);
    
      },
      props: {
        list: {
          type: Array,
          default: () => {
            return this.list || [];
          }
        }
      },
      methods: {
        handelClick: function(item) {
          console.log(item, "item");
        }
      }
    });
    var vm = new Vue({
      el: "#app",
      data: {
        list: [{
          id: 1,
          txt: 'javaScript',
          odd: true
        }, {
          id: 2,
          txt: 'Vue',
          odd: false
        }, {
          id: 3,
          txt: 'React',
          odd: true
        }]
      }
    });

    v-model

    之前的写法

    //HTML
    <div id="app">
      <vv-models v-model="txt" :txt="txt"></vv-models>
    </div>
    //js
    //input
    Vue.component('vv-models', {
      props: ['txt'],
      template: '<div>
             <p>看官你输入的是:{{txtcout}}</p>
             <input v-model="txtcout" type="text" />
           </div>',
      computed: {
        txtcout:{
          get(){
            return this.txt;
          },
          set(val){
            this.$emit('input', val);
          }
    
        }
      }
    });
    var vm = new Vue({
      el: "#app",
      data: {
        txt: '',
      }
    });

    render这样写

    //HTML
    <div id="app">
      <vv-models v-model="txt" :txt="txt"></vv-models>
    </div>
    //js
    //input
    Vue.component('vv-models', {
      props: {
        txt: {
          type: String,
          default: ''
        }
      },
      render: function(h) {
        var self=this;
        return h('div',[h('p','你猜我输入的是啥:'+this.txt),h('input',{
          on:{
            input(event){
              self.$emit('input', event.target.value);
            }
          }
        })] );
      },
    });
    var vm = new Vue({
      el: "#app",
      data: {
        txt: '',
      }
    });
  • 相关阅读:
    Docker容器启动时初始化Mysql数据库
    使用Buildpacks高效构建Docker镜像
    Mybatis 强大的结果集映射器resultMap
    Java 集合排序策略接口 Comparator
    Spring MVC 函数式编程进阶
    换一种方式编写 Spring MVC 接口
    【asp.net core 系列】6 实战之 一个项目的完整结构
    【asp.net core 系列】5 布局页和静态资源
    【asp.net core 系列】4. 更高更强的路由
    【Java Spring Cloud 实战之路】- 使用Nacos和网关中心的创建
  • 原文地址:https://www.cnblogs.com/SharkChilli/p/9962252.html
Copyright © 2011-2022 走看看