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: '',
      }
    });
  • 相关阅读:
    CSS知识(18---21.CSS完毕)
    CSS 知识(13---)
    CSS编辑知识 ( 1---12 )
    CSS 选择器
    前端CSS
    修建泳池的题解
    2020-3-7模拟赛题解
    奶牛排队的题解
    数的拆分的题解
    青蛙王子的题解
  • 原文地址:https://www.cnblogs.com/SharkChilli/p/9962252.html
Copyright © 2011-2022 走看看