1. 程式人生 > >Vue全家桶實踐(五)---渲染函式&JSX

Vue全家桶實踐(五)---渲染函式&JSX

最近公司要重寫運營管理系統,不想再維護之前的backbone了,趕緊要求前端整個重寫。重開新坑,用了兩週多擼出了第一版,收穫很大。在實踐中學習永遠都是最高效的。趁熱把學到的東西都記錄總結下來,也算簡單梳理一下思路。

相關部落格:

渲染函式&JSX

參考資料:文件

使用vue進行開發的時候,絕大部分情況下直接使用template來建立html,但在某些情況下,使用js會更有效。官方文件中就舉了生成h標籤的例子。
html的DOM樹種,每個元素都是一個節點,比如html標籤,文字,註釋等。
Vue通過建立虛擬DOM,對真實DOM的變化進行追蹤,通過createElement函式,返回一個虛擬節點(VNode),它包含的資訊會告訴Vue頁面上需要渲染出什麼元素。而虛擬DOM就是由這些VNode組成的樹。
實際上,我們在vue單檔案元件中寫的template,也會先被解析為VNode進行操作,然後再變成html在瀏覽器中渲染。

createElement引數

官網上有詳細的createElement用例。使用js替代template時,v-if使用if/else代替,v-for使用map代替即可。而v-model就要自己實現。
但是可以看到,實際上要使用createElement函式來生成一個VNode是很麻煩的,比如:

//template
<div id="container" @click="clickHandler">
    <p>Hello</p>
<div>
// createElement
// @returns {VNode}
createElement(
  'div'
, { attrs: { id: 'container' }, on: { click: this.clickHandler }, }, [ createElement('p', 'Hello') ] )

簡單的一段模板,用createElement程式碼量就大了很多,所以我們更多的使用jsx語法,讓我們更加接近模板。如:

import AnchoredHeading from './AnchoredHeading.vue'

new Vue({
  el: '#demo',
  render (h) {
    return
( <AnchoredHeading level={1}> <span>Hello</span> world! </AnchoredHeading> ) } })

將 h 作為 createElement 的別名是 Vue 生態系統中的一個通用慣例,實際上也是 JSX 所要求的,如果在作用域中 h 失去作用,在應用中會觸發報錯。
我們在使用iview的時候,就經常會需要用到render函式,例如:

// 簡單模板:
render (h, params) {
  return (
    <div>
      <p>{params.row.contactName}</p>
      <p>{params.row.phone}</p>
      <p>{params.row.email}</p>
    </div>
  )
}
// 迴圈
render (h, params) {
  return (
    <div>
      {params.row.data.map((item) => {
        return (<tag class='cursorDefault' type='border' color='blue'>{item}</tag>)
      })}
    </div>
  )
}
// 判斷&元件巢狀
render (h, params) {
  if (params.row.data=== null) {
    return
  }
  return (
    <poptip title='網店' trigger='hover' placement='left'>
      <tag color='blue'>{params.row.data}</tag>
      <div slot='content'>
        {params.row.eshops.map((shop) => {
          return (<p>{shop.title}</p>)
        })}
      </div>
    </poptip>
  )
}
// 事件繫結,使用箭頭函式確定作用域。
render: (h, params) => {
  return (
    <p class="xxx" onClick={ () => { this.changeTime(params.row) } }>
      <icon size="16" color="#19be6b" type="edit" />
      {moment(params.row.time).format('YYYY-MM-DD HH:mm:ss')}
    </p>
  )
}