【问题标题】:How generic/specific should HTML5 web components created with vanilla JavaScript be?使用 vanilla JavaScript 创建的 HTML5 Web 组件应该有多通用/特定?
【发布时间】:2015-10-20 05:18:39
【问题描述】:

我正在使用 HTML5 Web 组件(HTML 导入、影子 DOM、模板和自定义 HTML 元素)设计一个 Web 应用程序,该组件是用 vanilla JavaScript(无框架)实现的。 Web 应用程序相当简单,并且必须作为单页应用程序来实现。应用程序的部分要求是用户界面应该是可定制的。

设计方法

该示例使用<application-navigation> 自定义元素。此元素通过自定义事件(例如,new CustomEvent('application-navigation', {location:'/sign-in'}))和方法调用(例如,document.querySelector('application-navigation').enableSignOut())与“顶级”JavaScript(例如,JavaScript MV* 用语中的“路由器”)进行通信。本质上,自定义事件和方法构成了元素的“公共 API”。

可以使用不同的 HTML 导入将自定义的 <application-navigation> 元素包含在应用程序中。例如,使用 <link rel="import" href="default/application-navigation.html"/><link rel="import" href="my_cool_theme/application-navigation.html"/>。只要 HTML 导入具有相同的方法并产生相同的自定义事件,应用程序的功能就应该相同,而不管使用的是什么用户界面自定义。

这种设计的主要好处是它通过允许非常可定制的用户界面来满足要求 - 内部 JavaScript 事件、CSS 和(影子)DOM 结构可以在模板之间完全不同。它还允许在适当的时候重用现有的库。例如,默认的<application-navigation> 元素可以使用来自 Twitter Bootstrap 的下拉 HTML 标记,而主题版本可以使用 Foundation 库。

但是,这个组件不是很通用。它实现了一个相当特定的目的(控制导航请求),不像<application-dropdown> 元素(尽管<application-navigation> 元素可以使用(可定制的)<application-dropdown> 元素)。

重述问题

我的问题是,应该创建自定义元素来实现特定目的、更通用目的,还是目的的广度无关紧要?

【问题讨论】:

    标签: javascript css html web-component custom-element


    【解决方案1】:

    您可以构建特定或通用的自定义元素。两者都是相关的。

    然而,定义自定义元素的主要好处是能够轻松重用它们。所以我想说自定义元素通常是通用

    关于架构,你可以设计通用的技术元素,然后你可以用它们组成特定的功能元素。


    无论如何,使用相同的标签名称创建 2 个不同的组件并不是一个好主意。您宁愿使用另一种方法来实现您的目标(使用属性或内部元素来自定义您的自定义元素,或者给它另一个名称)。

    这是一个将主题定义为元素属性的示例:

    //CUSTOM ELEMENT
    var proto = Object.create( HTMLElement.prototype )
    
    proto.createdCallback = function ()
    {
      console.log( "{created}" )
      var html = document.querySelector( "template" )
      this.innerHTML = html.innerHTML
    }
    
    proto.attributeChangedCallback = function ( attr, old, val )
    {
      console.log( "{changed} attr=%s, old=%s, new=%s", attr, old, val )
    }
    
    var AN = document.registerElement( "application-navigation", { 
      prototype: proto 
    } )
    
    //EVENTS
    function add ()
    {
      if ( AN )
        document.body.appendChild( new AN )
    }
    
    function theme ( name )
    {
      var elem = document.querySelector( "application-navigation" )
      if ( elem )
        elem.setAttribute( "theme", name )
        }
    
    function load ()
    {
      var link = document.createElement( "link" )
      link.rel = "stylesheet"
      link.href = "/content/green.css"
      document.head.appendChild( link )
    }
    application-navigation[theme=blue] {
    			color: blue ;
    		}
    		application-navigation[theme=red] {
    			color: red ;
    		}
    <!DOCTYPE html>
    <html>
    <head>
    	<meta charset="utf-8" />
      <title></title>
    </head>
    <body>
    	<nav>
    		<button onclick="add()">Add Custom Element</button>
    		<button onclick="theme('red')">Change First to Red</button>
    		<button onclick="load()">External CSS</button>
    	</nav>
    	<template>
    		<h1>Title</h1>
    		<p>Custom Element Content</p>
    	</template>
    
    	<application-navigation theme="blue"></application-navigation>
    </body>
    </html>

    在上面的示例中,您甚至可以加载相对 URL 为 /content/green.css 的外部 CSS 文件:

    application-navigation[theme=blue] * {
        color: limegreen ;
    }
    
    application-navigation[theme=red] p {
        color: green ;
    }
    
    application-navigation[theme=red] h1 {
        color: orange ;
    }
    

    【讨论】:

    • 您有此类定制示例的链接吗?
    • 我已经用这种自定义的例子更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    相关资源
    最近更新 更多