无需传入连线的同构 hyperHTML 组件
Isomorphic hyperHTML components without passing in wires
我有以下两个组成部分:
// component.js
// imports ...
function ListItem(item) {
const html = wire(item)
function render() {
return html`<li>${item.foo}</li>`
}
return render()
}
function List(items) {
const html = wire(items)
function render() {
return html`<ul>${items.map(ListItem)}</ul>`
}
return render()
}
我想将它们放在客户端和服务器之间共享的模块中。然而,据我所知,尽管 API 几乎相同,但在服务器上我必须从 viperHTML 模块导入函数,在客户端上我必须使用 hyperHTML 模块。因此,我不能只在我的共享模块顶部导入函数,而是必须在调用站点传递给我的组件。
这样做我的同构组件将如下所示:
// component.js
function ListItem(html, item) {
//const html = wire(item) // <- NOTE
function render() {
return html`<li>${item.foo}</li>`
}
return render()
}
function List(html, itemHtmls /* :( tried to be consistent */, items) {
//const html = wire(items) // <- NOTE
function render() {
return html`<ul>${items.map(function(item, idx) {
return ListItem(itemHtmls[idx], item)
})}</ul>`
}
return render()
}
从服务器调用组件:
// server.js
const {hyper, wire, bind, Component} = require('viperhtml')
const items = [{foo: 'bar'}, {foo: 'baz'}, {foo: 'xyz'}]
// wire for the list
const listWire = wire(items)
// wires for the children
const listItemWires = items.map(wire)
const renderedMarkup = List(listWire, listItemWires, items)
从浏览器调用完全相同,除了导入 hyperhtml 的方式:
// client.js
import {hyper, wire, bind, Component} from 'hyperhtml/esm'
但是写这样的代码感觉很不愉快,因为我觉得 wire() 调用的结果应该存在于组件实例中。有没有更好的方法来编写同构 hyperHTML/viperHTML 组件?
更新 现在 hypermorphic 模块提供了一个解决方法。
理想情况是您只有 viperhtml
作为依赖项,这又会自动引入 hyperhtml
,正如您在 the index.js file.
中看到的那样
到那时,客户端捆绑器应该(如果有能力)为您摇树未使用的代码,但您有一个非常好的观点,但不是立即清楚。
我也不完全确定捆绑器是否可以那么聪明,假设像 typeof document === "object"
这样的检查总是正确的并且只针对浏览器。
一种尝试的方法是
import {hyper, wire, bind, Component} from 'viperhtml'
在客户端也是如此,希望它不会在捆绑后引入 viperHTML 依赖项,因为浏览器上有很多你永远不需要的东西。
I have a feeling that the result of the wire() calls should live
inside the component instances.
您可以使用 viper.Component 简化您的组件,这样您将拥有 render() { return this.html... }
而您忘记了绕过电线,但我同意您的看法,还有改进的余地。
到那时,您只需要解决 Component
在一个地方导入的问题,并定义可在客户端和服务器上运行的可移植组件。
这基本上就是灯 Component
存在的首要原因,它让您可以自由地专注于组件,而无需考虑连接什么,如何 and/or 哪里(如果 client/server).
~~我本来打算给你看一个例子,但你将内容与项目相关联(正确地)这一事实让我认为当前的组件也可以改进,所以 I've created a ticket as follow up 适合你的情况,我希望我'迟早会有更好的例子(组件)~~
编辑
我已经更新了库,让您可以创建能够 use/receive data/items 的组件,a code pen example。
class ListItem extends Component {
constructor(item) {
super().item = item;
}
render() {
return this.html`<li>${this.item.foo}</li>`;
}
}
class List extends Component {
constructor(items) {
super().items = items;
}
render() {
return this.html`
<ul>${this.items.map(item => ListItem.for(item))}</ul>`;
}
}
当您使用组件时,您要确保自己可以跨 client/server.
移植这些组件
目前唯一的问题是找出检索 Component
class.
的最佳方法
一种可能的解决方案是将此类 class.
的导出集中在单个入口点中
然而,房间里的大象是 NodeJS 与 ESM 模块不兼容,浏览器与 CommonJS 不兼容所以我没有最好的答案,因为我不知道 if/how 你正在捆绑您的代码。
理想情况下,您会使用 CommonJS,它在 NodeJS 中开箱即用,并且与每个浏览器捆绑器兼容,但您需要在每个构建中区分将导出 Component
或任何的文件其他 hyper/viperHTML 相关实用程序。
我希望我已经给了你足够的提示来最终解决当前的限制。
抱歉,如果我现在没有更好的答案。我以前使用的方法 external renders 但它很可能不是处理更复杂的结构/组件的最方便的方法。
P.S。你可以像这样写那些函数
function ListItem(item) {
return wire(item)`<li>${item.foo}</li>`;
}
function List(items) {
return wire(items)`<ul>${items.map(ListItem)}</ul>`;
}
我有以下两个组成部分:
// component.js
// imports ...
function ListItem(item) {
const html = wire(item)
function render() {
return html`<li>${item.foo}</li>`
}
return render()
}
function List(items) {
const html = wire(items)
function render() {
return html`<ul>${items.map(ListItem)}</ul>`
}
return render()
}
我想将它们放在客户端和服务器之间共享的模块中。然而,据我所知,尽管 API 几乎相同,但在服务器上我必须从 viperHTML 模块导入函数,在客户端上我必须使用 hyperHTML 模块。因此,我不能只在我的共享模块顶部导入函数,而是必须在调用站点传递给我的组件。
这样做我的同构组件将如下所示:
// component.js
function ListItem(html, item) {
//const html = wire(item) // <- NOTE
function render() {
return html`<li>${item.foo}</li>`
}
return render()
}
function List(html, itemHtmls /* :( tried to be consistent */, items) {
//const html = wire(items) // <- NOTE
function render() {
return html`<ul>${items.map(function(item, idx) {
return ListItem(itemHtmls[idx], item)
})}</ul>`
}
return render()
}
从服务器调用组件:
// server.js
const {hyper, wire, bind, Component} = require('viperhtml')
const items = [{foo: 'bar'}, {foo: 'baz'}, {foo: 'xyz'}]
// wire for the list
const listWire = wire(items)
// wires for the children
const listItemWires = items.map(wire)
const renderedMarkup = List(listWire, listItemWires, items)
从浏览器调用完全相同,除了导入 hyperhtml 的方式:
// client.js
import {hyper, wire, bind, Component} from 'hyperhtml/esm'
但是写这样的代码感觉很不愉快,因为我觉得 wire() 调用的结果应该存在于组件实例中。有没有更好的方法来编写同构 hyperHTML/viperHTML 组件?
更新 现在 hypermorphic 模块提供了一个解决方法。
理想情况是您只有 viperhtml
作为依赖项,这又会自动引入 hyperhtml
,正如您在 the index.js file.
到那时,客户端捆绑器应该(如果有能力)为您摇树未使用的代码,但您有一个非常好的观点,但不是立即清楚。
我也不完全确定捆绑器是否可以那么聪明,假设像 typeof document === "object"
这样的检查总是正确的并且只针对浏览器。
一种尝试的方法是
import {hyper, wire, bind, Component} from 'viperhtml'
在客户端也是如此,希望它不会在捆绑后引入 viperHTML 依赖项,因为浏览器上有很多你永远不需要的东西。
I have a feeling that the result of the wire() calls should live inside the component instances.
您可以使用 viper.Component 简化您的组件,这样您将拥有 render() { return this.html... }
而您忘记了绕过电线,但我同意您的看法,还有改进的余地。
到那时,您只需要解决 Component
在一个地方导入的问题,并定义可在客户端和服务器上运行的可移植组件。
这基本上就是灯 Component
存在的首要原因,它让您可以自由地专注于组件,而无需考虑连接什么,如何 and/or 哪里(如果 client/server).
~~我本来打算给你看一个例子,但你将内容与项目相关联(正确地)这一事实让我认为当前的组件也可以改进,所以 I've created a ticket as follow up 适合你的情况,我希望我'迟早会有更好的例子(组件)~~
编辑
我已经更新了库,让您可以创建能够 use/receive data/items 的组件,a code pen example。
class ListItem extends Component {
constructor(item) {
super().item = item;
}
render() {
return this.html`<li>${this.item.foo}</li>`;
}
}
class List extends Component {
constructor(items) {
super().items = items;
}
render() {
return this.html`
<ul>${this.items.map(item => ListItem.for(item))}</ul>`;
}
}
当您使用组件时,您要确保自己可以跨 client/server.
移植这些组件目前唯一的问题是找出检索 Component
class.
一种可能的解决方案是将此类 class.
的导出集中在单个入口点中然而,房间里的大象是 NodeJS 与 ESM 模块不兼容,浏览器与 CommonJS 不兼容所以我没有最好的答案,因为我不知道 if/how 你正在捆绑您的代码。
理想情况下,您会使用 CommonJS,它在 NodeJS 中开箱即用,并且与每个浏览器捆绑器兼容,但您需要在每个构建中区分将导出 Component
或任何的文件其他 hyper/viperHTML 相关实用程序。
我希望我已经给了你足够的提示来最终解决当前的限制。
抱歉,如果我现在没有更好的答案。我以前使用的方法 external renders 但它很可能不是处理更复杂的结构/组件的最方便的方法。
P.S。你可以像这样写那些函数
function ListItem(item) {
return wire(item)`<li>${item.foo}</li>`;
}
function List(items) {
return wire(items)`<ul>${items.map(ListItem)}</ul>`;
}