如何使用 Scala.js React 库从 React Bootstrap 库创建模态组件?
问问题
180 次
1 回答
1
Modal 必须更改状态(显示 = true/false)以显示/隐藏对话框这一事实使得解决方案变得不简单。我通过将它包装在一个具有可以更改的布尔状态的组件中来解决这个问题 - 当它需要显示/隐藏时,我会更改具有不纯效果的状态。
另一个问题是,如果 Modal 具有需要更改状态的按钮,则它们的事件处理程序需要以某种方式访问此状态。我通过让组件的用户在创建时访问组件的后端来解决了这个问题。
这是我对模态的实现:
class Modal(bs: BackendScope[Unit, Boolean], onHide: => Unit, children: Modal => Seq[ChildArg]) {
def render(show: Boolean) = {
val props = (new js.Object).asInstanceOf[Modal.Props]
props.show = show
props.onHide = () => {
dismiss()
onHide
}
Modal.component(props)(children(this): _*)
}
def dismiss() = {
bs.withEffectsImpure.setState(false)
}
}
object Modal {
@JSImport("react-bootstrap", "Modal")
@js.native
object RawComponent extends js.Object
@js.native
trait Props extends js.Object {
var show: Boolean = js.native
var onHide: js.Function0[Unit] = js.native
}
val component = JsComponent[Props, Children.Varargs, Null](RawComponent)
type Unmounted = Scala.Unmounted[Unit, Boolean, Modal]
def apply(onHide: => Unit = Unit)(children: Modal => Seq[ChildArg]): Unmounted = {
val component = ScalaComponent.builder[Unit]("Modal")
.initialState(true)
.backend(new Modal(_, onHide, children))
.renderBackend
.build
component()
}
}
以及使用它的 Dialog 对象:
object Dialog {
object Response extends Enumeration {
type Response = Value
val OK, CANCEL = Value
}
import Response._
def prompt(title: String, body: String, okText: String): Future[Response] = {
// Add an element into which we render the dialog
val element = dom.document.body.appendChild(div(id := "dialog").render).asInstanceOf[Element]
// Create a promise of a return and a method to send it
val p = Promise[Response]
def respond(ret: Response) = {
// Remove the containing element and return the response
dom.document.body.removeChild(element)
p.success(ret)
}
Modal(respond(Response.CANCEL)) { modal =>
// Function to dismiss the dialog and respond
def quit(ret: Response) = {
modal.dismiss()
respond(ret)
}
// Create the components for our Modal
Seq(
ModalHeader(true,
ModalTitle(title)
),
ModalBody(body),
ModalFooter(
Button(variant = "secondary", onClick = () => { quit(Response.CANCEL) })("Cancel"),
Button(variant = "primary", onClick = () => { quit(Response.OK) })(okText)
)
)
}.renderIntoDOM(element).backend
p.future
}
}
于 2019-07-10T07:42:59.227 回答