vue render 渲染函數


vue render 渲染函數

經常看到使用render渲染函數的示例,而且在一些特殊情況下,確實更好使用,可以更加有效地細分組件,因而借助vue-element-admin來學習一波

render函數分析

  • 函數式組件
  • 基礎的使用方式

針對 Link.vue進行改造

Link.vue

// https://github.com/vuejs/eslint-plugin-vue/issues/462
<template>
  <!-- eslint-disable vue/require-component-is -->
  <component v-bind="linkProps(to)">
    <slot />
  </component>
</template>

<script>
import { isExternal } from '@/utils/validate'
export default {
  props: {
    to: {
      type: String,
      required: true
    }
  },
  methods: {
    linkProps(url) {
      if (isExternal(url)) {
        return {
          is: 'a',
          href: url,
          target: '_blank',
          rel: 'noopener'
        }
      }
      return {
        is: 'router-link',
        to: url
      }
    }
  }
}
</script>

上述方式打開了一個新的使用方式,這樣的好處,不需要使用if/else進行處理,還可以減少一個多余的標簽【root element】。但是會有一些語法提示錯誤,雖然添加了eslint-disable來禁止,但還是不行,而且有些不似vue的用法

改造開始

  • 版本一 非函數式組件 【Link.vue】
<script>
import { isExternal } from '@/utils/validate'

export default {
  name: 'Link',
  props: {
    to: {
      type: String,
      required: true
    }
  },
  render(h) {
    if (isExternal(this.to)) {
      return h(
        'a',
        {
          attrs: {
            target: '_blank',
            rel: 'noopener',
            href: this.to
          }
        },
        this.$slots.default
      )
    } else {
      return h('router-link',
        {
          props: {
            to: this.to
          }
        },
        this.$slots.default
      )
    }
  }
}
</script>

主要是slot如何處置比較好,其他都好處理,而且使用slot有兩種方式 插槽

方式一

this.$slots.default

方式二

this.$scopedSlots.default()
  • 版本二 函數式組件 【Link.vue】
<script>
import { isExternal } from '@/utils/validate'

export default {
  name: 'Link',
  functional: true,
  props: {
    to: {
      type: String,
      required: true
    }
  },
  render(h, context) {
    console.log(context)
    const { props, scopedSlots } = context
    const { to } = props
    if (isExternal(to)) {
      return h(
        'a',
        {
          attrs: {
            target: '_blank',
            rel: 'noopener',
            href: to
          }
        },
        scopedSlots.default()
      )
    } else {
      return h('router-link',
        {
          props: {
            to: to
          }
        },
        // scopedSlots.default()
        context.children
      )
    }
  }
}
</script>

對於上述兩種實現方式,大致相同,有一些細節需要注意

  • functional: true 添加這個后,只能通過 context來進行上下文關聯,而無法調用this,同時這種方式會快一些,只是在使用slot時,會有兩種形式link
    • this.$slots.default 更新為 context.children
    • scopedSlots.default() 這種方式依舊在
  • 當時用functional: true,文件名便可以改為js為后綴了,若依舊使用vue時,便需要<script> export default {}</script> 進行包裹了

總結

  • render函數更多是,很多細節不能使用語法糖來進行處理,導致使用起來不順手
  • slot插槽這塊還是很有用的,只是文檔說明等沒有前面的那么詳細了
  • 通過上述方式,便發現原來可以這么玩,而且細粒度已經都要一層標簽了,若使用原來的方式,root element怕是就夠處理好一會兒了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM