Html 创建具有不同子类型的自定义图元
我目前正在使用自定义元素(web组件)实现一个数据表元素。该表可以有不同类型的单元格(文本、数字、日期等),用于呈现每一行 例如Html 创建具有不同子类型的自定义图元,html,css,dom,web-component,custom-element,Html,Css,Dom,Web Component,Custom Element,我目前正在使用自定义元素(web组件)实现一个数据表元素。该表可以有不同类型的单元格(文本、数字、日期等),用于呈现每一行 例如 我还有一个MyTableCell类,所有单元格元素都扩展了该类。这对于共享公共功能很好,但是样式设计可能会很麻烦,因为每个单元格类型都有自己的html标记。目前,我在扩展MyTableCell时添加了一个css类,但为了论证起见,假设我不想这样做 理想的解决方案是能够使用is关键字扩展自定义元素,例如 我可以想出三种解决这个问题的方法: 语法类似于,但这需要更多
我还有一个MyTableCell
类,所有单元格元素都扩展了该类。这对于共享公共功能很好,但是样式设计可能会很麻烦,因为每个单元格类型都有自己的html标记。目前,我在扩展MyTableCell
时添加了一个css类,但为了论证起见,假设我不想这样做
理想的解决方案是能够使用is
关键字扩展自定义元素,例如
我可以想出三种解决这个问题的方法:
,但这需要更多的工作,因为您不再扩展基类,而是创建同一元素的变体,这意味着您需要一种注册不同变体的自定义方式,比如静态MyTableCell.registerType
包装在一个通用的
中。这避免了自定义寄存器方法,但它更难编写,并导致更多元素和更多样板代码,这反过来意味着性能下降
,单元格在内部使用类似document.createElement('my-table-rendener-'+类型)
。这保留了选项1的简单语法,同时仍然避免了自定义寄存器方法,但它具有与选项2相同的性能含义你能提出更好的选择吗?我遗漏了什么吗?可以做的是使用
定制的内置元素:
<table is="data-table>
<tr>
<td is="data-string">Bob</td>
<td is="data-date">11/1/2017</td>
<td is="data-number">44<td>
</tr>
</table>
class CellElement extends HTMLElement {
constructor () {
super()
//create cell
switch ( this.getAttribute( 'type' ) )
{
case 'string':
this.view = new CellStringView( this )
break
default:
this.view = new CellView( this )
}
}
connectedCallback () {
//render cell
this.view.render()
}
}
通过这种方式,所有单元扩展相同的
元素,共享一个公共原型,但有自己的方法实现
您可以重写共享方法,共享方法可以调用派生原型对象的特定方法
请参见此处的运行示例:
//表
类DataTable扩展了HTMLTableElement{
构造函数(){
超级()
console.info('data table created')
}
}
define('DataTable',DataTable,{extends:'table'});
//细胞
类DataCell扩展了HTMLTableCellElement{
connectedCallback(){
console.info('cell connected')
if(typeof this.renderContent=='function')
this.renderContent()
}
}
//细胞串
类StringCell扩展了DataCell{
renderContent()
{
console.info('datastringrender')
this.innerHTML='“'+this.textContent.trim()+'”
}
}
定义('datastring',StringCell,{extends:'td'})
表格{
边界塌陷:塌陷;
}
td,th{
边框:1px纯色灰色;
填充:2件
}
测试表扩展v1
身份证姓名年龄
1和20
2 Bob 31
NB:这个答案与另一个答案是分开的,因为它本身相当广泛,完全独立
如果使用具有(可选)类型
属性的自治自定义元素(即自定义标记):
<data-table>
<data-row>
<data-cell>1</data-cell>
<data-cell type="string">An</data-cell>
<data-cell type="number">20</data-cell>
</data-row>
</data-table>
在自定义元素定义(可被视为控制器)中:
- 创建时,实例化视图(或模型)
- 如果要渲染单元格(或处理数据),请调用视图(或模型)的(覆盖或不覆盖)方法
<table is="data-table>
<tr>
<td is="data-string">Bob</td>
<td is="data-date">11/1/2017</td>
<td is="data-number">44<td>
</tr>
</table>
class CellElement extends HTMLElement {
constructor () {
super()
//create cell
switch ( this.getAttribute( 'type' ) )
{
case 'string':
this.view = new CellStringView( this )
break
default:
this.view = new CellView( this )
}
}
connectedCallback () {
//render cell
this.view.render()
}
}
下面是一个实时片段:
//视图(MVC视图)
类CellView{
构造函数(视图){
this.view=视图
}
render(){}
}
//字符串视图
类CellStringView扩展了CellView{
render(){
console.info('special rendering',this.view)
this.view.innerHTML='“'+this.view.textContent+'”
}
}
//元件(MVC控制器)
类CellElement扩展了HtmleElement{
构造函数(){
超级()
//创建单元
开关(this.getAttribute('type')){
大小写“string”:
this.view=新的CellStringView(this)
打破
违约:
this.view=新单元视图(this)
}
}
connectedCallback(){
//渲染单元
this.view.render()
}
}
自定义元素。定义('data-cell',CellElement)
数据表{
显示:表格;
边界塌陷:塌陷;
边框:1px纯色灰色;
}
数据行{
显示:表格行;
}
数据单元{
显示:表格单元格;
边框:1px实心#ccc;
填充:2px;
}
自定义表v1
身份证件
名称
年龄
1.
一
20
2.
上下快速移动
31
您想用v0或v1规范设计定制元素吗?我对这两种都很满意。目前正在使用v0,直到更多浏览器添加对v1的本机支持。据我所知,两个规范都有相同的限制,即不能使用is
扩展自定义元素。我不明白下面的注释。使用自定义标记是我现有的解决方案(我的通用原型是上面提到的MyTableCell)。这可以用于共享功能,但有我试图避免的样式问题,因为所有单元格类型都定义自己的标记。我的节点是关于行为的。就样式而言,对于自定义标记,使用单个元素。它仍然不同于您的#2-3解决方案,因为您不需要在其中插入自定义元素。这与我的示例中的选项1基本相同,不同之处在于视图是在switch语句中预定义的。与选项1一样,如果希望允许用户定义自己的视图,则需要一种注册视图的方法,以便CellElement可以实例化视图。你以前的答案没有答案
class CellElement extends HTMLElement {
constructor () {
super()
//create cell
switch ( this.getAttribute( 'type' ) )
{
case 'string':
this.view = new CellStringView( this )
break
default:
this.view = new CellView( this )
}
}
connectedCallback () {
//render cell
this.view.render()
}
}