vue render

官網描述的場景當咱們開始寫一個經過 level prop 動態生成 heading 標籤的組件,你可能很快想到這樣實現:html

<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>。java

雖然模板在大多數組件中都很是好用,可是在這裏它就不是很簡潔的了。那麼,咱們來嘗試使用 render 函數重寫上面的例子:express

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中。api

createElement參數介紹數組

接下來你須要熟悉的是如何在 createElement 函數中生成模板。這裏是 createElement 接受的參數:app

createElement(
 // {String | Object | Function}
 // 一個 HTML 標籤字符串,組件選項對象,或者
 // 解析上述任何一種的一個 async 異步函數,必要參數。
 'div',

 // {Object}
 // 一個包含模板相關屬性的數據對象
 // 這樣,您能夠在 template 中使用這些屬性。可選參數。
 {
  // (詳情見下一節)
 },

 // {String | Array}
 // 子節點 (VNodes),由 `createElement()` 構建而成,
 // 或使用字符串來生成「文本節點」。可選參數。
 [
  '先寫一些文字',
  createElement('h1', '一則頭條'),
  createElement(MyComponent, {
   props: {
    someProp: 'foobar'
   }
  })
 ]
)

 

深刻 data 對象dom

有一件事要注意:正如在模板語法中,v-bind:class 和 v-bind:style ,會被特別對待同樣,在 VNode 數據對象中,下列屬性名是級別最高的字段。該對象也容許你綁定普通的 HTML 特性,就像 DOM 屬性同樣,好比 innerHTML (這會取代 v-html 指令)。ssh

{
 // 和`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接下來我們就來點實戰。async

以前這樣寫

//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: '',
  }
});
相關文章
相關標籤/搜索