博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vue高阶组件
阅读量:6276 次
发布时间:2019-06-22

本文共 5808 字,大约阅读时间需要 19 分钟。

vue高阶组件

高阶组件的定义

  • 高阶组件是一个函数,它将一个组件作为参数并返回新创建的组件。返回的组件通常使用HOC(高阶组件)提供的功能进行扩充。
  • 高阶组件不是可以抓取和安装的软件,而是一种可以帮助编写可重用和可维护代码的技术方案。

示例

  1. BlogPost(博文),CommentsList(评论列表)为例代码如下:
# App.vue
# components/CommentsList.vue
# components/BlogPost.vue
# source.jsconst listeners = {};const comments = ['comment one', 'comment two', 'comment three', 'comment four', 'comment five'];const blogPosts = { 1: `Lorem ipsum dolor sit amet, utinam scripta splendide ei cum. Mediocrem dissentiet est ut, nec tale ullum no, has putent scaevola mediocrem an. Ex quot latine denique vim, ne quot quaeque sea. In pri habeo diceret, an ius tale voluptatum, ad liber facilis minimum vis. Eos iriure concludaturque id, sed inani nulla interesset in, labores adipiscing dissentiet vel ut.`, 2: 'Peek-A-Boo!'}setInterval(() => { comments.push(`fresh comment ${comments.length + 1}`) Object.keys(blogPosts).forEach(id => { blogPosts[id] = `${blogPosts[id]} ${comments.length}` })}, 5000)export default { getComments() { return comments; }, getBlogPost(id) { return blogPosts[id]; }, addChangeListener(listener) { const intervalId = setInterval(() => { listener() }, 1000) listeners[listener] = intervalId }, removeChangeListener(listener) { clearInterval(listeners[listener]) }}复制代码
  • 从BlogPost、CommentsList组件可以看出它们结构非常相似,现作如下说明:
  1. 从DataSource中获取数据(如:DataSource.getComments()、DataSource.getBlogPost())
  2. 更新外部数据源中每次更新的数据(handleChange方法)
  3. 将更改侦听器添加到数据源(mounted方法)
  4. 从数据源中删除更改侦听器(beforeDestroy方法)
为了避免代码重复,可以将BlogPost和CommentsList之间的共享逻辑提取到高阶组件中,下面是实现步骤。复制代码
  1. 高阶组件一步一步演化
  • 此时,高阶组件不会做太多。它只需要一个组件并创建一个呈现传递组件的新组件。代码如下:
# hocs/withSubscription.jsimport Vue from 'vue'import CommentsList from '~/components/CommentsList.vue'const withSubscription = (component) => {  return Vue.component('withSubscription', {    render(createElement) {      return createElement(component)    }   }}const CommentsListWithSubscription = withSubscription(CommentsList)复制代码
  • 实现共享逻辑,添加mount,beforeDestroy钩子和handleChange方法。代码如下:
# hocs/withSubscription.jsimport DataSource from '../store/source'import Vue from 'vue'const withSubscription = (component) => {    return Vue.component('withSubscription', {        render(createElement) {            return createElement(component)        },        methods: {            handleChange() {            }        },        mounted() {            DataSource.addChangeListener(this.handleChange)        },        beforeDestroy() {            DataSource.removeChangeListener(this.handleChange)        }    })}export default withSubscription复制代码
- 现在,高阶组件返回的新组件需要生命周期钩子。 handleChange方法保留为空。两个组件都具有handleChange方法,但是,此方法在每个组件中的实现略有不同- 高阶组件可以接受多个参数。目前,withSubscription仅接受组件作为参数。为了在handleChange中调用自定义逻辑,需要第二个参数。第二个参数是应该在每次数据源更改时调用的方法。代码如下复制代码
# hocs/withSubscription.jsimport DataSource from '../store/source'import Vue from 'vue'const withSubscription = (component, selectData) => {return Vue.component('withSubscription', {        render(createElement, context) {            return createElement(component, {               props: {                  content: this.fetchedData               }            })        },        data() {            return {                fetchedData: null            }        },        methods: {            handleChange() {                this.fetchedData = selectData(DataSource)            }        },        mounted() {            DataSource.addChangeListener(this.handleChange)        },        beforeDestroy() {            DataSource.removeChangeListener(this.handleChange)        }    })}export default withSubscription复制代码
  • App.vue中使用高阶组件的代码如下
# App.vue
复制代码
  • BlogPost and CommentsList代码如下
# components/BlogPost.vue
----# components/CommentsList.vue
复制代码
- 到目前阶段,组件渲染是正常的,可以为自己打个call,毕竟取得了一定的成果,但是并不完美,需进一步完善。假设我需要将博客文章ID传递给BlogPost怎么办?或者如果我需要从BlogPost发布一个事件到App组件又该怎么办?复制代码
  • 处理高阶组件中的props
# App.vue
---# components/BlogPost.vue
复制代码
  • 高阶组件的调整
# hocs/withSubscription.jsimport DataSource from '../store/source'import Vue from 'vue'const withSubscription = (component, selectData) => {    const originalProps = component.props || [];    return Vue.component('withSubscription', {        render(createElement) {            return createElement(component, {                props: {                    ...originalProps,                    content: this.fetchedData                }            })        },        props: [...originalProps],        data() {            return {                fetchedData: null            }        },        methods: {            handleChange() {                this.fetchedData = selectData(DataSource, this.$props)            }        },        mounted() {            DataSource.addChangeListener(this.handleChange)        },        beforeDestroy() {            DataSource.removeChangeListener(this.handleChange)        }    })}export default withSubscription复制代码
- 从原组件BlogPost获取props保存到originalProps中,withSubscription高阶组件props接收originalProps的值,以便以后能够将它们传递给BlogPost组件复制代码
  • 处理高阶组件中的处理事件
# App.vue
---# components/BlogPost.vue
复制代码
  • 要记住重要的一点,我们不直接在App中渲染BlogPost,有一个中间组件 - withSubscription HOC。 为了将事件监听器传递给渲染组件,我需要在高阶组件中添加一行代码。withSubscription代码作如下调整
# hocs/withSubscription.jsreturn Vue.component('withSubscription', {    ...    on: {...this.$listeners} # <= this line,})复制代码

参考链接

转载地址:http://itgpa.baihongyu.com/

你可能感兴趣的文章
embedded linux学习中几个需要明确的概念
查看>>
mysql常用语法
查看>>
Morris ajax
查看>>
【Docker学习笔记(四)】通过Nginx镜像快速搭建静态网站
查看>>
ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
查看>>
<转>云主机配置OpenStack使用spice的方法
查看>>
java jvm GC 各个区内存参数设置
查看>>
[使用帮助] PHPCMS V9内容模块PC标签调用说明
查看>>
关于FreeBSD的CVSROOT的配置
查看>>
基于RBAC权限管理
查看>>
基于Internet的软件工程策略
查看>>
数学公式的英语读法
查看>>
留德十年
查看>>
迷人的卡耐基说话术
查看>>
PHP导出table为xls出现乱码解决方法
查看>>
PHP问题 —— 丢失SESSION
查看>>
Java中Object类的equals()和hashCode()方法深入解析
查看>>
数据库
查看>>
Vue------第二天(计算属性、侦听器、绑定Class、绑定Style)
查看>>
dojo.mixin(混合进)、dojo.extend、dojo.declare
查看>>