Hyperstack 中的高阶组件
Higher-order components in Hyperstack
javascript 库有一个常见的用例,您希望在其中用高阶组件装饰您的组件。
例如,material-ui 库包含样式化高阶组件 withStyles
。
在javascript,你会做
import { withStyles } from '@material-ui/core';
const styles = {
example: {
padding: 8
}
}
const SomeComponent = ({classes}) => <div className={classes.example}>I'm a component</div>;
export default withStyles(SomeComponent);
如何在 Hyperstack 中实现相同的功能?
首先看起来有一个 issue 您必须修补。这将在下一个小版本中修复:只需将此方法添加到您的 Hypercomponent
基础 class (app/hyperstack/components/hypercomponent.rb
)
def self.to_n
Hyperstack::Internal::Component::ReactWrapper.create_native_react_class(self)
end
现在如果你有以下款式:
MY_STYLES = {root: {backgroundColor: 'red'}}
以及您要设置样式的组件:
class StyleTest < HyperComponent
param :some_param
param :classes
render do
DIV(class: classes[:root]) { some_param }
end
end
您可以这样做:
class StyledTest1 < HyperComponent
imports `Mui.withStyles(#{MY_STYLES.to_n})(#{StyleTest.to_n})`
end
发生的事情是我们使用反引号退出 JS 并直接调用 Mui.with_styles
并传递它 MY_STYLES
(就像在 MUI 文档示例中一样)。 to_n
从 Ruby Hash 转换为 JS 对象。 (当将参数传递给组件时,这是自动的,但对于简单的函数调用则不是这样。)
然后我们用 StyleTest
class 调用生成的 HOC(还调用 to_n
将 Ruby class 转换为简单的 JS class.)
最后,我们将其导入回 Hyperstack 组件 class。
这比我喜欢的工作多了一点,所以我们可以在我们的 HyperComponent
class:
中添加一个方便的辅助方法
class HyperComponent
include Hyperstack::Component
include Hyperstack::State::Observable
param_accessor_style :accessors # this is now the prefered param style
# patch for issue: https://github.com/hyperstack-org/hyperstack/issues/153
def self.to_n
Hyperstack::Internal::Component::ReactWrapper.create_native_react_class(self)
end
# our helper macro:
def self.add_styles(style, opts = {})
imports `Mui.withStyles(#{style.to_n}, #{opts.to_n})(#{superclass.to_n})`
end
end
现在我们可以像这样添加样式:
class StyledTest2 < StyleTest
add_styles MY_STYLE
end
现在我们有了一个新的组件 Class,其中包含我们的样式。
例如:
class App < HyperComponent
render do
DIV do
StyledTest1(some_param: 'test 1')
StyledTest2(some_param: 'test 2')
end
end
end
javascript 库有一个常见的用例,您希望在其中用高阶组件装饰您的组件。
例如,material-ui 库包含样式化高阶组件 withStyles
。
在javascript,你会做
import { withStyles } from '@material-ui/core';
const styles = {
example: {
padding: 8
}
}
const SomeComponent = ({classes}) => <div className={classes.example}>I'm a component</div>;
export default withStyles(SomeComponent);
如何在 Hyperstack 中实现相同的功能?
首先看起来有一个 issue 您必须修补。这将在下一个小版本中修复:只需将此方法添加到您的 Hypercomponent
基础 class (app/hyperstack/components/hypercomponent.rb
)
def self.to_n
Hyperstack::Internal::Component::ReactWrapper.create_native_react_class(self)
end
现在如果你有以下款式:
MY_STYLES = {root: {backgroundColor: 'red'}}
以及您要设置样式的组件:
class StyleTest < HyperComponent
param :some_param
param :classes
render do
DIV(class: classes[:root]) { some_param }
end
end
您可以这样做:
class StyledTest1 < HyperComponent
imports `Mui.withStyles(#{MY_STYLES.to_n})(#{StyleTest.to_n})`
end
发生的事情是我们使用反引号退出 JS 并直接调用 Mui.with_styles
并传递它 MY_STYLES
(就像在 MUI 文档示例中一样)。 to_n
从 Ruby Hash 转换为 JS 对象。 (当将参数传递给组件时,这是自动的,但对于简单的函数调用则不是这样。)
然后我们用 StyleTest
class 调用生成的 HOC(还调用 to_n
将 Ruby class 转换为简单的 JS class.)
最后,我们将其导入回 Hyperstack 组件 class。
这比我喜欢的工作多了一点,所以我们可以在我们的 HyperComponent
class:
class HyperComponent
include Hyperstack::Component
include Hyperstack::State::Observable
param_accessor_style :accessors # this is now the prefered param style
# patch for issue: https://github.com/hyperstack-org/hyperstack/issues/153
def self.to_n
Hyperstack::Internal::Component::ReactWrapper.create_native_react_class(self)
end
# our helper macro:
def self.add_styles(style, opts = {})
imports `Mui.withStyles(#{style.to_n}, #{opts.to_n})(#{superclass.to_n})`
end
end
现在我们可以像这样添加样式:
class StyledTest2 < StyleTest
add_styles MY_STYLE
end
现在我们有了一个新的组件 Class,其中包含我们的样式。
例如:
class App < HyperComponent
render do
DIV do
StyledTest1(some_param: 'test 1')
StyledTest2(some_param: 'test 2')
end
end
end