此篇文章不只是为讲解在电视机顶盒WEB环境开发的经验,也包含对于简化后浏览器内核的开发环境与低性能设备踩坑。css
由于发现目前针对于机顶盒的前端开发分享很是之少,质量也广泛不高,在此作记录分享,文章中所用技术皆为前端技术,不包含Andoird等其余语言,可放心食用。前端
因为市面机顶盒生产厂商不少,其中表现基本都有区别,也有内置机顶盒功能的网络电视,因此在硬件不一样的基础上,采用统一的软件服务环境开发是颇有必要的。react
本人开发项目所项目运行环境是Android部门基于Chrome内核的某个版本作技术支持而打包的环境(其中抛弃了某些特性 好比不支持视频音频Cookie等),但有的盒子已经在市场上使用了几年,性能很低,使用的也是更低版本的内核,致使开发上会有一些阻碍,因此若您的环境也有所差别,技术上有疑惑,可留言告诉我。android
目前市面上开发团队用的比较多的框架无非是 React、Vue、Angular,但在此不推荐用这些东西,而是使用jQuery做为开发的基础支持,插件等效果本身开发实现——为了性能与加载速度。由于这些框架的插件在电脑上运行是没有压力的,但若在机顶盒上,其实能够再优化一些的,与其优化别人的代码不如本身写一个 ~ 若是你webpack学得不错,能够搭建一个以jQuery为核心的打包环境,优化加载方式与速度,那就更好了。webpack
1.遥控器每次点击后跳转一次新的页面,都会重新请求其余页面的数据,在页面onload以前,android为了避免让用户看到闪白,是以黑屏状态显示页面的,当页面加载完成后触发onload,才会展示页面。如若使用框架三巨头来作,页面加载性能会慢那么一点点,固然,能够经过prefetch作优化,但这不是主要缘由,请往下看。css3
2.简化后的浏览器内核对history对象的支持不友好,若是使用react-router,会致使后退出现bug。git
3.公司业务开发速度的考量,jQuery较为方便敏捷,不要喜新厌旧,实用才是最重要的。github
一行文字放不下怎么办?动画循环滚动之 文字单行跑马灯 (做者对于CSS动画兼容性没有作适配,须要修改JS源码,加入CSS前缀的生成)web
这里可分享的暂此一个插件,由于目前对于盒子上能用到的插件推荐很少,我注重性能,喜欢写针对于盒子性能优化后的代码逻辑,在尽力的状况下不浪费一丝丝内存(贫穷令人拮据)算法
好比一定会用到的滚动动画插件,市面上的例如swpie.js已经很成熟了,也很流畅,但对于盒子环境而言仍是有些慢,还能够作二次优化,因此我基本习惯本身去写,但插件的源码没法放出,我会在下面章节的 “功能实现分析” 中写出大概思路。
根据工做上的业务需求,我会罗列出产品常常想要的功能,并分析相关的思路。
这能够说是项目中一定出现的需求,先说下视觉上动画的实现方式
注:毫不要使用jQuery的animate
如:
固定宽度滚动:
子元素宽度固定已知,只须要知道当前光标在第几个元素,带入index到固定的算法,便可获取滚动距离,较为简单
未知宽度滚动:
元素宽度、个数、排序规则未知,可能有十几种不一样的宽度,排序的方式是后台定义,若想从右向左滚动下一屏,滚动时机是什么?怎样的时机才是好的体验?
如何计算?
1.如非必要,请避免动态获取参数,已知参数写入DOM标签或DOM内存,不要去动态获取元素的宽/高/边距/距离父级的位置,这对于盒子而言是很耗性能的事情,这些东西能够放在初始化列表的时候轮询计算。
好比有一个列表宽度未知,可能知足滚动五屏的列表,列表还没有滚动,left值则为0
子元素可能有50列,那么第一列 col-01 宽100px 边距18px 第二列 col-02 宽130 边距 = 第一列边距+第一列宽+第二列边距
实际代码:
<div class="listBox"><!--固定容器宽高 好比宽100%高100% 随窗口大小固定-->
<div class="list" data-width="266" data-left="0"><!--须要滚动的列表容器 宽度随内部元素宽度改变-->
<a class="col-01" data-width="100" data-left="18">第一列</a><!--left = 自身边距 + 前面元素宽度+边距 没有则为0-->
<a class="col-02" data-width="130" data-left="136">第二列</a><!--left = 自身边距+前面元素宽度+边距-->
</div>
</div>
复制代码
if( 滚动列表容器宽 > 父级固定容器宽 && 焦点元素宽+焦点元素left+下一个元素的边距好比18 > 当前视口的宽){
//存在第二页 && 当前元素焦点看不到下一个元素
则在此处使列表稍微多滚动几像素 露出至少1像素的边缘 使盒子能够检测到右侧有焦点能够移动
}
复制代码
这样算下去明显很复杂,那么有没有简单点的方法呢 ?
将他们加载的时候都存入内存的数组中,监听用户按键并阻止默认行为,计算当前焦点在数组的第几个,用户按右键就向后移动一次,查询页面上对应的DOM,再计算他将要去的位置便可,这样获取焦点的任务就交给了咱们本身,而不是机顶盒,可控性上升,未知性下降,但不变的是咱们仍是要预先存入DOM的data-width,data-left等值,为何不存入内存中而写入标签?也能够存,好比jQuery获取DOM后的 $(dom).data("data-left",500),但产品这时候又提出了一个功能:我要后退时还原前一个页面的状态~
这个功能讲起来就是:简单的页面就简单,复杂的页面就很麻烦
但一般都是经过 storage实现的,那咱们就先讲它
其实产品想要的就是跳走前什么样,回来就什么样而已
若是是一个简单的页面(没有滚动,元素就那么几个)
直接在跳走前点击A标签的时候,以当前页面的url为键值
focusJson对象 写入跳走前点击A标签它的ClassName、Href地址、Index值,返回此页时根据这三个值匹配到后,得知跳走前的元素是哪儿个
const seStorage = window.sessionStorage;
const pageUrl = window.location.href.split("?")[0];
const QUOTA_EXCEEDED_ERR_CODE = 22;
$(a).click(function(){
const focusJson = {
className : $(this).attr("class"),
href : $(this).attr("href"),
index: $(this).index()
}
try {
seStorage.setItem(pageUrl, focusJson);
} catch (e) {
//防止存不下报错 理应不会出现 由于咱们要在页面按返回,或初次进入页面的时候清除掉当前页Storage 防止溢出
//但仍是避免下用户连续进超多页面 不按返回的状况
if (e.code === QUOTA_EXCEEDED_ERR_CODE) {
seStorage.clear();
seStorage.setItem(pageUrl, focusJson);
}
}
})
...
$(function(){
//页面初始化时查询是否存有storage 如有则寻找对应className 过滤出正确的元素还原焦点状态 并清除本次storage
})
复制代码
产品开发项目时间紧,不够你考虑优化的时候采用此方案,时间充裕不建议这样,由于不优雅
那就是直接CopyDOM节点转字符串存入storage,回到此页直接扔到页面里去 通常焦点都会有全局惟一的样式名作焦点效果,直接Focus此样式元素,就完整的还原了跳走前的状态
但须要注意如下几点:
1.页码记录,跳走前把动态数据已经请求的页码也存入focusJson,还原的时候载入这个页码,这样往下翻页数据才正确
2.若是这个动态数据页面存在滚动列表,且滚动了不少屏,如何还原?
若是采用上面在标签中写入data-left,data-width的方式,实际上还原后直接将这些参数做为滚动插件初始化时的初始值便可,绑定到滚动插件就能够正常使用了,只写大概思路,实现具体方式须要本身研究哈,感受并不复杂
复制代码
3.DOM数据量太大,存入会致使Storage溢出
没错 这就是简单粗暴的缺点,大量的data-left,data-width,DOM标签都存入在storage,数据量大的状况下确实会溢出,须要考虑项目使用场景,数据量的大小
复制代码
对于前端而言,能在内存中处理的就不要放在DOM上,灵活的操做数据才是王道,好比React的虚拟DOM与Diff算法,咱们能够在初始化页面列表的时候就将这些元素的left,width等数据存入对象中,转存入storage,在页面初始化的时候读取storage像Ajax请求JSON同样解析它来还原列表,只记录关键的属性值,而不用像上面简单粗暴的方式把那些根本不须要记录的dom标签、class、id等不属于数据的垃圾字节存起来占地方,能够很大的节省storage的存储空间,若是你的项目时间充裕建议以此方案进行开发,不要将就。
很不幸的是:并非全部浏览器环境都支持storage,有的环境支持sessionStorage 有的环境sessionStorage和localStorage都支持,而有的环境他们都不支持 …… 那咱们就没办法了吗?
input type="text"标签实现记录
1.不能使用type="hidden" 它记录不到的,返回后数据会消失
2.不能使用css的display:none 也会致使返回数据丢失
那么让它这么占着位置也难看,能够有两种方法解决:
1.positoin:absolute; 哪儿远让它去哪儿
2.visibility:hidden; 占位但隐藏,与display:none不一样的是它不会使数据丢失
因为页面都是A标签元素的跳转,咱们能够经过监听focus事件得知本次焦点的是哪儿个元素,给它一个焦点样式,并取消上一个焦点样式 例如
$(document).on("foocus","a",function(){
$(".itemFocus").removeClass("itemFocus");
$(this).addClass("itemFocus");
});
复制代码
但这样就会有一个问题 若是你的页面是动态加载、翻页,页面有100个A标签,你每次Focus都要查询这些标签是否存在itemFocus
假若还要计算元素的滚动等,那对于用户而言,操做时明显会有响应慢的问题,那么咱们能够简单优化下:
let $focus = null;
$(document).on("foocus","a",function(){
$focus === null? $(".itemFocus").removeClass("itemFocus") : $focus.removeClass("itemFocus");
$focus = $(this).addClass("itemFocus");
});
复制代码
这样每次都把以前的焦点元素存入了内存,下次就不须要轮询查找.itemFocus,效率获得了显著的提高
先写到这里吧,原本想写的不少,但发现写起来是真的累,深感倒不如学些东西去
盒子WEB开发者比较少,先看看可否帮助部分人踩坑吧!