浅谈组件增强
来源:互联网 发布:房产中介端口推荐 编辑:程序博客网 时间:2024/06/14 21:33
11月的上海,褪去了一丝温暖,夹带着丝丝寒意。独自一人走在街上,望着路边的男男女女,不禁让我想起了那个前任的她。因为有她,我才学会了做饭,学会照顾人,学会怎么谦让,不过在生命的进程中,她不过是一个过客罢了,她的出现和离开,对我都没有本质的改变。一阵寒风吹过,我再次抬头,是啊,刚才的故事蛮好的,是时候来知乎分享刚编的故事了,显然,程序员并不会有前任。
细细想一想,其实生活中存在很多起修饰作用的东西,万物本通,在编程界,也有许多的起修饰作用的东东,而且基于这个概念还发展出了许许多多的名称。
装饰函数
来首先看第一个装饰函数,函数可以接受参数并且返回值。如果接受的值和返回的一样呢?如果我们有一个构造函数:
function Person(name) {
this.name = name
}
Person.prototype.greet = function() {
console.log('hello:' + this.name)
}
现在由于 Person 函数是被封装的,不可以改变其源代码,而又想在先增加一个输出时间的方法,再调用原输出。就可以简单采用如下方式:
const cloudic = new Person('cloudic')
cloudic.greet() // => hello:cloudic
// 函数直接包装
function sayDate(f, ...args) {
console.log('show date')
typeOf f === 'funciton' && f(...args)
}
cloudic.dateGreet = sayDate(cloudic.greet)
cloudic.dateGreet() // => show date hello:cloudic
// 采用原型继承包装
function DateDecorator(man) {
const newMan = Object.create(man)
newMan.greet = function() {
console.log('show date')
man.greet()
}
return newMan
}
const newCloudic = DateDecorator(cloudic)
newCloudic.greet() // => show date hello:cloudic
这样子类的更改并不会影响其他子类,当然第一种看起来更加简单点,如果希望所做的改变能同步影响到子类,可以覆盖原型对象上同名的方法,当然也可以用 decorator 语法糖。
为什么想动态增加个功能这样繁琐呢,JS 是动态语言,在运行的时候,可以方便的修改对象的属性,但是由于函数存在作用域的限制,想要动态修改函数内部的变量很难实现。所以才绕着弯子,采用包装的方式来实现。换个角度想下,如果一个对象或者函数内部提供了一个方法,该方法可以动态的修改函数内部的变量,那我们只需要调用该方法即可,这样的模式暂且叫中间件模式吧,比如 redux 的中间件。
高阶组件
说回组件层面,如果把上面说的应用到组件上,那么就是传入一个组件返回另外一个组件。在 React 中,我们比较常用的叫 HOC 模式,常见的实现方式如下:
function HOC(WrappedComponent) {
return class Wrap extends React.Component {
render() {
return <WrappedComponent {...this.props}/>
}
}
}
在使用的时候,只需要传入需要包装的组件,调用函数后会返回一个包装过的组件。这样的好处是通过避免直接调用原组件,采用类似代理的方式来间接调用,从而可以方便后期替换原组件,可以做适配器,同时相比于 mixin 的实现方式,高阶组件更容易被调试,由于 mixin 是混入模式,导致在组件之间共享的代码很隐晦,如果方法比较多的话,还可能会覆盖现有的组件,所以 React 官方废弃了 mixin 的模式,推崇高阶组件来代替组件之间共享代码。
抽象组件
在 Vue 中,如果想对一个组件或者 DOM 进行相关功能的增强,我们可以用下面几种方式:
其一我们可以想到是采用指令的形式:
Vue.directive('name', {
inserted: function (el) {
// do something...
}
})
指令可以方便的增加功能和复用,但是指令不能使用回调函数,不能传 props,没有事件,导致使用起来的灵活度不高。指令更多的是做 DOM 层面的工作,封装一些方法来修饰元素或操作元素属性。
其二我们可以用函数式组件:
Vue.component('name', {
functional: true,
render: function (createElement, context) {
// ...do something
},
// Props 可选
props: {
// ...
}
})
函数式组件不会被实例化,也就是没有 data 和 this 上下文,也不能使用事件回调。可以简单的认为就是一个函数而已。不过函数式组件的优点也在于此,并不会有额外的性能开销,从而可以提高程序的性能。
其三就是采用抽象组件:
Vue.component('name', {
abstract: true,
render: function (createElement) {
return this.$slots.default[0]
}
})
抽象组件在 Vue 官网并没有文档介绍,因为这是一个内部组件定义的功能,不是很稳定,随时可能会更改,并且不会通知到你。Vue 内置的组件比如 keep-alive, transition, component, slot 都是抽象组件,抽象组件没有自己的 DOM 元素,只是简单增加功能然后返回子元素。和纯函数组件相比,它有自己的生命周期,会被实例化,内部有this,是一个真正的组件,所以可以用 emit 发放事件。
总结
在组件增强的各个方法中,每个都有优劣,至于到底选择那个,还是需要使用者根据业务场景来决定。
原文:https://zhuanlan.zhihu.com/p/30818429
- 浅谈组件增强
- 浅谈增强学习
- ListView增强组件QuickScroll
- 找增强出口,一点浅谈
- 增强现实(Augmented Reality)浅谈
- 增强现实(Augmented Reality)浅谈
- 浅谈Android Service 组件
- 浅谈Android Service 组件
- Bean组件管理浅谈
- 浅谈Android Service 组件
- 浅谈组件技术
- EXTJS组件化浅谈
- Android四大组件浅谈
- 浅谈iOS组件化
- 浅谈React表单组件
- 浅谈hadoop个组件
- 浅谈如何增强ASP程序性能
- 浅谈Mysql5.7的Replication相关增强
- @QueryParam和@PathParam的区别
- 流感传染
- BZOJ2588 Count on a tree 【树上主席树】
- AWS深度学习摄像头,将对机器学习产业有何影响?
- 意见征集,世界AI智商评测量标准2018年新版讨论方案
- 浅谈组件增强
- 计算距离
- hadoop的HA高可用机制配置搭建
- Chrome 浏览器 必知必会的小技巧
- 如何写好.babelrc?Babel的presets和plugins配置解析
- 前后台交互
- 关于反爬虫,看这一篇就够了
- 随笔
- Android Studio导入第三方库SDK(jar)的方法