Vue源码分析(高阶函数)

高阶函数

高阶函数在函数式编程中经常出现,就是你原本有一个函数,你可以通过另外一个函数进行包裹,这个新的函数既具有原来函数的功能,又可以添加自己的功能,这种方式称为高阶函数。

我们现在有一个函数组件Avatar,它接收一个src属性并显示到img标签

<avatar url="/path/to/image.png"></avatar>

上面是它的使用方式,可以看到我们使用的时候需要传递完整的图片地址,这很不方便。现在希望我们只需要传递用户名,就可以自动根据用户名查询到url。

这里我们使用高阶组件,创建一个函数组件withAvatarURL,这个函数接收内部组件,本例中内部组件就是Avatar,我们在外部函数中完成根据用户名查询头像地址,在内部函数组件Avatar中实现渲染头像。

fetchURL只是用来模拟网络请求的,我们设置0.5s后返回数据,Avatar是基础组件,只负责把传入src属性显示到一个图片标签。

<script src="../node_modules/vue/dist/vue.js"></script>

<div id="app">
  <smart-avatar username="vuejs"></smart-avatar>
</div>

<script>
// mock API
function fetchURL (username, cb) {
  setTimeout(() => {
    // hard coded, bonus: exercise: make it fetch from gravatar!
    cb('https://avatars3.githubusercontent.com/u/6128107?v=4&s=200')
  }, 500)
}

const Avatar = {
  props: ['src'],
  template: `<img :src="src">`
}

function withAvatarURL (InnerComponent) {
  return {
    props: {
      username: String
    },
    data () {
      return {
        url: 'http://via.placeholder.com/200x200'
      }
    },
    created () {
      fetchURL(this.username, (url) => { this.url = url })
    },
    render (h) {
      return h(InnerComponent, { props: { src: this.url } })
    }
  }
}

const SmartAvatar = withAvatarURL(Avatar)

new Vue({
  el: '#app',
  components: { SmartAvatar }
})
</script>

this.$attrs用于获取组件所有属性,这是2.4之后才支持的功能,下面代码我们把高阶组件设置的属性传递给原始组件。

	render (h) {
    
    
      return h(InnerComponent, {
    
    
        attrs: this.$attrs, // 2.4 only
        props: {
    
    
          src: this.url || 'http://via.placeholder.com/200x200'
        }
      })
    }

高阶函数和mixin的选择

上面的demo同样可以使用mixin实现,但是高阶组件有如下优势

  1. 重用性。mixin对原组件有侵入性,会导致原组件可重用性降低。而高阶组件不会,高阶组件对原组件只是一个调用关系,并没有修改原来组件任何内容。
  2. 可测试性。因为高阶组件只是一个嵌套关系,在组件测试的时候,可以单独的测试原始组件和高阶组件。
  3. 层级问题。高阶组件也有他的弊端,如果你高阶组件嵌套层级太深,会导致出错的时候调试困难的问题,所以到底使用高阶组件和minxin需要看实际场景。

猜你喜欢

转载自blog.csdn.net/qq_47234456/article/details/126862348