先上效果预览:

Web Components

首先,什么是 Web Components ?

MDN 给出的定义是:

Web Components 是一套不同的技术,允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的web应用中使用它们。

... ...

实现web component的基本方法通常如下所示:

  1. 使用 ECMAScript 2015 类语法创建一个类,来指定web组件的功能(参阅类获取更多信息)。
  2. 使用 CustomElementRegistry.define() 方法注册您的新自定义元素 ,并向其传递要定义的元素名称、指定元素功能的类以及可选的,其所继承自的元素。
  3. 如果需要的话,使用 Element.attachShadow() 方法将一个 Shadow DOM 附加到自定义元素上。使用通常的 DOM 方法向 Shadow DOM 中添加子元素、事件监听器等等。
  4. 如果需要的话,使用 <template><slot> 方法定义一个 HTML 模板。再次使用常规 DOM 方法克隆模板并将其附加到您的 Shadow DOM 中。
  5. 在页面任何您喜欢的位置使用自定义元素,就像使用常规 HTML 元素那样。

说人话,就是先定义一个类

class MyCompo extends HTMLElement {
constructor() {
super(); // 一定要先调用 super
// 为所欲为
}
}

在里面实现需要的功能,比如给自己添加子元素和事件监听器,设置样式等,就像在写平常的 JS 代码一样。

然后,注册这个元素:

window.customElements.define('my-compo', MyCompo)

根据 CustomElements v1 标准,自定义元素的名称必须包含一个横线。

最后,在 HTML 里面写入这个标签:

<my-compo></my-compo>

标签必须有结束标签与之对应,不能使用自闭合标签。

然后就可以充分享受 CustomElements 带来的乐趣了,是不是很简单呢 (误

通常,Custom Elements 会与 ShadowDOM 结合使用。那什么是 ShadowDOM 呢?

ShadowDOM

MDN 给出的定义是:

An important aspect of web components is encapsulation — being able to keep the markup structure, style, and behavior hidden and separate from other code on the page so that different parts do not clash, and the code can be kept nice and clean. The Shadow DOM API is a key part of this, providing a way to attach a hidden separate DOM to an element.

大概翻译一下:

封装是 Web Components 中重要的一环,可以将元素的 DOM 树结构、样式以及行为逻辑与页面中的其他部分相隔离以避免冲突,并使你的代码保持整洁。 Shadow DOM API 是其中的关键部分,它提供了向元素中插入隐藏 DOM 子树的方法。

简言之,Shadow DOM API 可以在任意元素内部插入一个隔离的 DOM 子树,其中的元素与样式与外部 DOM 保持隔离,不会影响到外部。所以无需担心 CSS 代码相互冲突。

说了这么多,兼容性怎么样呢?

抱歉,打扰了(

但我们可以使用 Polyfill ,比如这个 webcomponentsjs ,这里就不展开介绍了。

我的博客园页面中已经加入了注入 Polyfill 的代码,如果你的浏览器不能正确加载,那真的改换浏览器了 ...

<script>
(function(w,d){
function i(p){var s=d.createElement('script');s.src=p;s.async=false;d.head.appendChild(s);}
var sd='attachShadow'in Element.prototype;
var ce='customElements'in window;
if (!sd && !ce) i('https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/bundles/webcomponents-sd-ce.js');
else if(!ce) i('https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/bundles/webcomponents-ce.js');
else if(!sd) i('https://cdn.jsdelivr.net/npm/@webcomponents/webcomponentsjs/bundles/webcomponents-sd.js');
i('https://cdn.jsdelivr.net/npm/melody-player/dist/player.min.js');
})(window,document);
</script>

MelodyPlayer

额,跑题了,今天发文章的目的其实是介绍播放器啊,播放器播放器~~~

首先,播放器支持两种模式,一种是单曲模式,就像这样:

默认播放一遍之后停止,也可以点击右边第二个按钮切换到单曲循环模式。

然后是列表模式,就像文章一开始时展示的那样,多了 上一曲 和 下一曲 的按钮,默认播放列表一遍后停止。也可以选择列表循环、单曲循环或是随机模式。

最右边的按钮可以展开/收起歌词面板。支持一或两个歌词同时显示,还有流畅的滚动动画。歌词加载失败后会有提示。

技术栈与优化

JS 部分使用了 ECMAScript 2015 各种语法,以及 JSX 。但并没有使用 React ,而是用 babel 自定义 JSX @pragma ,并实现了一个自定义的 createElement 。 Webpack 配置可以参见 这里

CSS 部分使用了 Less ,但并没有生成独立的样式文件,也没有用 style-loader 。在 Webpack 的配置中,仅使用 less-loader 将 *.less 转译为 *.css ,然后使用 css-loader 解析 CSS 中的 url() 部分,并在 JS 代码中将解析后的 CSS 字符串添加到 ShadowRoot 下。

图标使用了 Google 的 Material Design Icons ,但并没有全量引入。我只将需要用到的 10 个图标提取出来,生成了字体的子集,只有不到 1KB 大小。然后使用 url-loader 将字体转为 Data URL 并内联在 CSS 中。关于压缩字体的方法及原理,请移步我的独立博客:制作极限压缩的 Material Icons 图标字体

经过上述的优化,整个 melody-player.min.js 只有不到 23KB 的大小。


最后,附上 GitHub 链接,欢迎 Star ~

GitHub 仓库: rocka/melody-player

GitHub Demo: MelodyPlayer Demo

一个使用 Web Components 的音乐播放器: MelodyPlayer的更多相关文章

  1. 一个功能齐全的IOS音乐播放器应用源码

    该源码是在ios教程网拿过来的,一个不错的IOS音乐播放器应用源码,这个是我当时进公司时 我用了一晚上写的  图片都是在别的地方扒的,主要是歌词同步,及上一曲,下一曲,功能齐全了 ,大家可以学习一下吧 ...

  2. 用<audio>标签打造一个属于自己的HTML5音乐播放器

    上一章节,我们刚刚讲了<video>标签,今晚,我们讲的是<audio>标签,这两个东东除了表示的内容不一样以外,其他的特性相似的地方真的太多了,属性和用法几乎一样,也就说,如 ...

  3. 一个简单有趣的Python音乐播放器

    (赠新手,老鸟绕行0.0) Python版本:3.5.2 源码如下: __Author__ = "Lance#" # -*- coding = utf-8 -*- #导入相应模块 ...

  4. web常见之音乐播放器

    代码来源于:这位Github小伙伴,我只负责解说! 效果图如下: 先上HTML代码 源码: <!DOCTYPE html> <html> <head> <me ...

  5. 网页播放音频、视频文件——基于web的html 5的音乐播放器(转载)

    文章转载自:开源中国社区 [http://www.oschina.net] 想通过手机客户端(支持 Android.iPhone 和 Windows Phone)访问开源中国:请点这里 HTML5 是 ...

  6. 我在 Gitee 上发现了一个简洁又好用的网络音乐播放器!

    这几天无聊的时候我想听听歌,但我想要找一个简单快速的网络音乐播放器来用用.这时我在 Gitee 上看见一个看上去不错的开源项目 -- Hi音乐. 项目链接:https://gitee.com/hi-j ...

  7. Android 实现简单音乐播放器(二)

    在Android 实现简单音乐播放器(一)中,我介绍了MusicPlayer的页面设计. 现在,我简单总结一些功能实现过程中的要点和有趣的细节,结合MainActivity.java代码进行说明(写出 ...

  8. Android基于发展Service音乐播放器

    这是一个基于Service组件的音乐播放器,程序的音乐将会由后台的Service组件负责播放,当后台的播放状态改变时,程序将会通过发送广播通知前台Activity更新界面:当用户单击前台Activit ...

  9. vue——一个页面实现音乐播放器

    请忽略下面这段文字年关将至,时间好歹又多出了些许.却不敢过度消遣.岁月未曾饶过我,我亦不想饶过岁月.且将它塞得膨胀,让这一年看似加更充实.不曾料想我一个爱些风花雪月.研墨行歌之人,却做起了碼农这一行当 ...

随机推荐

  1. scrapy-redis使用以及剖析

    scrapy-redis是一个基于redis的scrapy组件,通过它可以快速实现简单分布式爬虫程序,该组件本质上提供了三大功能: scheduler - 调度器 dupefilter - URL去重 ...

  2. uvalive 5834 Genghis Khan The Conqueror

    题意: 给出一个图,边是有向的,现在给出一些边的变化的信息(权值大于原本的),问经过这些变换后,MST总权值的期望,假设每次变换的概率是相等的. 思路: 每次变换的概率相等,那么就是求算术平均. 首先 ...

  3. isinstance(obj1,class) 可以判断前者是否是后者的实例

    isinstance(obj1,class) 可以判断前者是否是后者的实例

  4. 使用hue查看hdfs系统报无法访问:/user/hadoop。 Note: you are a Hue admin but not a HDFS superuser, "hdfs" or part of HDFS supergroup, "supergroup".

    出现这个问题,是因为默认的超级用户是hdfs ,我的是hadoop用户登录的, 也就是说首次登录hadoop这个用户是我的超级用户 此时只需要将hue.ini配置改为 然后重启即可.

  5. contenteditable 插入及粘贴纯文本内容

    本文主要介绍 div 标签设置  contenteditable = ' true ' 时,在光标位置插入输入的内容,或在光标位置粘贴纯文本内容.文中涉及知识,可参考以下: http://www.zh ...

  6. 运用正则+replace+substring将一段英语的字母大写 angurlar运用自定义指令filter完成首字母大写

    复习下js基础并运用正则+replace+substring将一段英语的字母大写 <!DOCTYPE html><html> <head> <meta cha ...

  7. 实战分享:如何成功防护1.2T国内已知最大流量DDoS攻击

    作者:腾讯云宙斯盾安全团队&腾讯安全平台部 引言: DDoS攻击势头愈演愈烈,除了攻击手法的多样化发展之外,最直接的还是攻击流量的成倍增长.3月份国内的最大规模DDoS攻击纪录还停留在数百G规 ...

  8. Jenkins + Gradle + pgyer + Android自动发布

    Jenkins配置与必要的环境配置 一:Jenkins服务端(Linux系统为例说明): 1.jdk安装与配置 2.SDK安装与配置 3.安装配置对应的gradle版本(建议gradle版本在4.1版 ...

  9. LruCache的缓存策略

    一.Android中的缓存策略 一般来说,缓存策略主要包含缓存的添加.获取和删除这三类操作.如何添加和获取缓存这个比较好理解,那么为什么还要删除缓存呢?这是因为不管是内存缓存还是硬盘缓存,它们的缓存大 ...

  10. [Luogu 3690]【模板】Link Cut Tree (动态树)

    Description 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和. ...