制作一个 HTML 源对象

Making a HTML source object

我想创建一个 HTML 扩展,它提供一个标签 (uai),其格式类似于 <uai src="some_what_file.mp3" controller="nav" autoplay="true">

依此类推,此标签将分配一个 javascript 对象。

function uai(){
    this.src = { ... }
    this.controller = { ... }
    this.autoplay = { ... }
}

但我想知道如何将此函数作为对象应用到 html 标签,并使 HTML 标签将源应用到 this.src

此对象将类似于输入标签 *


我知道音频标签存在,我完全知道如何使用它。但我想用这个替换音频标签和功能。它将使我更容易制作 canvas 支持的音频标记,所以这就是我需要它的原因。

您可以像访问任何其他元素一样访问它,并使用它做您需要做的事情。

console.log(document.querySelector('cookies').getAttribute('flavor'))
<cookies flavor="chocolate chip"></cookies>

您应该注意两个重要问题:

首先,不能self-closing。浏览器以特殊方式处理 self-closing 元素 (<cookies />),并且你不能创建自定义 self-closing 标签(这也是像 Angular 这样的框架必须处理的限制和)。它必须有一个结束标签,即使它没有 children: <cookies></cookies>

其次,您不能像 document.querySelector('cookies').flavor 那样直接访问 属性。您需要使用 document.querySelector('cookies').getAttribute('flavor').setAttribute()。但是,您可以自己应用它以备后用:

Array.prototype.slice.call(document.querySelectorAll('cookies'), 0).forEach(cookie => Object.defineProperty(cookie, 'flavor', {
  get: () => cookie.getAttribute('flavor'), 
  set: (value) => cookie.setAttribute('flavor', value)
}));

let cookie = document.querySelector('cookies');
console.log(cookie.flavor);
cookie.flavor = 'sugar';
console.log(cookie.flavor);
console.log(cookie);
<cookies flavor="chocolate chip"></cookies>
<cookies flavor="peanut butter"></cookies>

使用支持 类 和扩展的转译器非常容易。

class UAIElement extends HTMLElement {

}

document.registerElement('uai', UAIElement);

纯js版本:

document.registerElement('uai', {
  prototype: Object.create(HTMLElement.prototype, {
   extends: 'audio'
  })
});

如果您想使用自定义元素,您需要在标签名称中插入一个连字符 - 以确保它不会在未来的标准中使用,例如:<ultimate-audio>.

您现在还应该使用自定义元素规范的 version 1,它使用 customElements.define() 而不是 document.registerElement() 来注册新元素。

最后,如果要创建新标签,则不能使用 extends:'audio' 选项。

您可以在所有现代浏览器中使用 class 定义:

ulimate-audio.html的内容:

<template>
    <h3>UAI</h3>
    <nav>
        <button id=PlayBtn>Play</button>
        <button id=StopBtn>Stop</button>
        <input id=AutoplayCB type=checkbox disabled>Auto-Play
        <div>Source : <output id=SourceOut></output></div>
    </nav>
</template>

<script>
( function ( owner )
{
    class UAI extends HTMLElement 
    {
        constructor ()
        {
            super()
            this.model = {}
            this.view = {}
        }

        connectedCallback ()
        {
          //View
            this.innerHTML = owner.querySelector( 'template' ).innerHTML
            this.view.autoplay = this.querySelector( '#AutoplayCB' )
            this.view.source = this.querySelector( '#SourceOut' )

          //Model
            //autoplay
            var attr =  this.getAttribute( 'autoplay' ) 
            this.model.autoplay =  typeof attr == 'string' && ( attr == '' || attr == 'true' ) 

            //source
            this.model.source = this.getAttribute( 'src' )


          //Model -> View
            this.view.source.textContent = this.model.source
            this.view.autoplay.checked = this.model.autoplay

          //[play] event
            var self = this
            this.querySelector( '#PlayBtn' ).addEventListener( 'click', function () 
            {
                self.play() 
            } )
            this.querySelector( '#StopBtn' ).addEventListener( 'click', function () 
            {
                self.stop() 
            } )

          //init
            if ( this.model.autoplay )
                this.play()
        }

        play ()
        {   
            this.model.audio = new Audio( this.model.source )
            this.model.audio.play()
        }

        stop ()
        {
            this.model.audio.pause()
        }

        set src ( file ) 
        {
            console.log( '%s.src=%s', this, file )
            this.model.source = file
            this.model.audio.src = file 
            this.view.source.textContent = file
            if ( this.model.autoplay )
                this.model.audio.play()
        }

        set autoplay ( value )
        {
            console.warn( 'autoplay=', value )
            this.model.autoplay = ( value === "true" || value === true )
            this.view.autoplay.checked = this.model.autoplay
        }

    }

    customElements.define( 'ultimate-audio', UAI )
} )( document.currentScript.ownerDocument ) 
</script>

您控件的UI定义在<template>中,您可以在其中添加一个<style>元素。 然后你可以像这样使用你的标签:

header 中包含自定义元素:

<link rel="import" href="ultimate-audio.html">

body中,使用新标签:

<ultimate-audio id=UA src="path/file.mp3" autoplay></ultimate-audio>

方法 play()stop() 以及属性 srcautoplay 可以从 javascript:

中调用
UA.src = "path/file2.mp3"
UA.play()