html+mui
本文仅用于个人学习,感谢批评指正
webview
Webview模块管理应用窗口界面,实现多窗口的逻辑控制管理操作。通过plus.webview可获取应用界面管理对象。
属性:
isRecovery: 当前Webview窗口是否由于内核崩溃自动恢复
方法:
all:获取所有Webview窗口
close:关闭Webview窗口
create:创建新的Webview窗口
currentWebview:获取当前窗口的WebviewObject对象
getDisplayWebview: 获取屏幕所有可视的Webview窗口
getWebviewById:查找指定标识的WebviewObject窗口
getLaunchWebview:获取应用首页WebviewObject窗口对象
getSecondWebview:获取第二个首页WebviewObject窗口对象
getTopWebview:获取应用栈顶的WebviewObject窗口对象
hide:隐藏Webview窗口
open:创建并打开Web窗口
postMessageTouniNView:向uniNView窗口发送消息
prefetchURLS:预载网络页面
prefetchURLS:预载多个网络页面
show:显示Webview窗口
startAnimation:Webview窗口组合动画
defaultHardwareAccelerated:获取Webview默认是否开启硬件加速
书写规范
对象:
AnimationTypeShow: 一组用于定义页面或控件显示动画效果
AnimationTypeClose: 一组用于定义页面或控件关闭的动画效果
WebviewObject: Webview窗口对象,用于操作加载HTML页面的窗口
WebviewAnimationOptions: Webview窗口动画参数
WebviewAnimationStyles: Webview窗口动画样式
WebviewBounceStyle: Webview窗口回弹样式
WebviewContentAnimationOptions: Webview窗口内容动画参数
WebviewDock: 原生控件在窗口中停靠的方式
WebviewDragEvent: Webview窗口滑动事件数据
WebviewDragOptions: 窗口手势操作参数
WebviewDragOtherViewOptions: 手势操作关联对象参数
WebviewDrawOptions: 截屏绘制操作参数
WebviewFavoriteOptions: 窗口收藏参数
WebviewLoadDataOptions: 创建加载HTML数据参数
WebviewShareOptions: 窗口的分享参数
WebviewSubNViewStyles: 窗口原生子View控件样式
WebviewTitleNViewStyles: 窗口标题栏控件样式
WebviewTitleNViewButtonStyles: 窗口标题栏自定义按钮样式
WebviewTitleNViewSearchInputStyles: 窗口标题栏搜索框样式
WebviewProgressStyles: 标题栏控件的进度条样式
WebviewSplitLineStyles: 窗口标题栏控件的分割线样式
WebviewEvent: Webview窗口事件
WebviewExtraOptions: JSON对象,原生窗口扩展参数
WebviewPosition: 原生控件在窗口中显示的位置
WebviewPullToRefreshStyles: Webview窗口下拉刷新样式
WebviewRenderedEventOptions: Webview窗口rendered事件参数
WebviewReplaceWebApiOptions: 替换H5标准API配置信息
WebviewStatusbarStyles: JSON对象,Webview窗口的系统状态栏区域样式
WebviewStyles: JSON对象,Webview窗口对象的样式
WebviewTransform: 一组用于定义页面或控件变形的属性
WebviewTransition: 一组用于定义页面或控件转换效果的属性
WebviewUniNViewStyles: uniNView原生渲染窗口样式
WebviewOverrideResourceOptions: 拦截Webview窗口资源请求的参数
WebviewOverrideUrlOptions: 拦截Webview窗口URL请求的属性
WebviewListenResourceOptions: 监听Webview窗口资源加载的属性
回调方法:
BounceEventCallback: Webview窗口回弹事件的回调函数
EventCallback: Webview窗口事件的回调函数
PopGestureCallback: Webview窗口侧滑事件的回调函数
HistoryQueryCallback: 历史记录查询的回调函数
ListenResourceLoadingCallback: Webview窗口加载资源事件的回调函数
OverrideUrlLoadingCallback: Webview窗口拦截URL链接跳转的回调函数
TitleUpdateCallback: Webview窗口加载页面标题更新的回调函数
WebviewAnimationCallback: Webview窗口组合动画回调函数
WebviewDragCallback: Webview窗口滑屏操作事件回调函数
WebviewCustomButtonCallback: Webview窗口标题栏上自定义按钮点击事件回调函数
SuccessCallback: Webview窗口操作成功回调函数
ErrorCallback: Webview窗口操作失败回调函数
创建新的Webview窗口
WebviewObject plus.webview.create( url, id, styles, extras );
说明:
创建Webview窗口,用于加载新的HTML页面,可通过styles设置Webview窗口的样式,创建完成后需要调用show方法才能将Webview窗口显示出来。
显示Webview窗口
void plus.webview.show( id_wvobj, aniShow, duration, showedCB, extras );
说明:
显示已创建或隐藏的Webview窗口,需先获取窗口对象或窗口id,并可指定显示窗口的动画及动画持续时间。
隐藏Webview窗口
void plus.webview.hide( id_wvobj, aniHide, duration, extras );
说明:
根据指定的WebviewObject对象或id隐藏Webview窗口,使得窗口不可见。
获取当前窗口的WebviewObject对象
WebviewObject plus.webview.currentWebview();
说明:
获取当前页面所属的Webview窗口对象。
查找指定标识的WebviewObject窗口
**WebviewObject plus.webview.getWebviewById( id );**
说明:
在已创建的窗口列表中查找指定标识的Webview窗口并返回。 若没有查找到指定标识的窗口则返回null,若存在多个相同标识的Webview窗口,则返回第一个创建的Webview窗口。 如果要获取应用入口页面所属的Webview窗口,其标识为应用的%APPID%,可通过plus.runtime.appid获取。
创建并打开Webview窗口
WebviewObject plus.webview.open( url, id, styles, aniShow, duration, showedCB );
说明:
创建并显示Webview窗口,用于加载新的HTML页面,可通过styles设置Webview窗口的样式,创建完成后自动将Webview窗口显示出来。
以上来源于html5plus文档,只列举了部分最常用的方法。
模块:
5+功能模块(permissions)
{
// ...
"permissions":{
// ...
"Webview": {
"description": "窗口管理"
}
}
}
ui组件
官方文档mui-ui
窗口管理
页面初始化
在app开发中,若要使用HTML5+扩展api,必须等plusready事件发生后才能正常使用,mui将该事件封装成了mui.plusReady()方法,涉及到HTML5+的api,建议都写在mui.plusReady方法中。如下为打印当前页面URL的示例:
mui.plusReady(function(){
console.log("当前页面URL:"+plus.webview.currentWebview().getURL());
});
使用webview就需要和plusReady一起使用
mui.init() mui插件初始化
mui.ready() 当DOM准备就绪时,指定一个函数来执行。
代码块激活字符: minit
打开新页面
做web app,一个无法避开的问题就是转场动画;web是基于链接构建的,从一个页面点击链接跳转到另一个页面,如果通过有刷新的打开方式,用户要面对一个空白的页面等待;如果通过无刷新的方式,用Javascript移入DOM节点(常见的SPA解决方案),会碰到很高的性能挑战:DOM节点繁多,页面太大,转场动画不流畅甚至导致浏览器崩溃; mui的解决思路是:单webview只承载单个页面的dom,减少dom层级及页面大小;页面切换使用原生动画,将最耗性能的部分交给原生实现。
mui.openWindow({
url:new-page-url,
id:new-page-id,
styles:{
top:newpage-top-position,//新页面顶部位置
bottom:newage-bottom-position,//新页面底部位置
width:newpage-width,//新页面宽度,默认为100%
height:newpage-height,//新页面高度,默认为100%
......
},
extras:{
.....//自定义扩展参数,可以用来处理页面间传值
},
createNew:false,//是否重复创建同样id的webview,默认为false:不重复创建,直接显示
show:{
autoShow:true,//页面loaded事件发生后自动显示,默认为true
aniShow:animationType,//页面显示动画,默认为”slide-in-right“;
duration:animationTime//页面动画持续时间,Android平台默认100毫秒,iOS平台默认200毫秒;
},
waiting:{
autoShow:true,//自动显示等待框,默认为true
title:'正在加载...',//等待对话框上显示的提示内容
options:{
width:waiting-dialog-widht,//等待框背景区域宽度,默认根据内容自动计算合适宽度
height:waiting-dialog-height,//等待框背景区域高度,默认根据内容自动计算合适高度
......
}
}
})
参数说明:
styles:表示窗口参数,参考5+规范中的WebviewStyle;特别注意,height和width两个属性,即使不设置,也默认按100%计算;因此若设置了top值为非"0px"的情况,建议同时设置bottom值,否则5+ runtime根据高度100%计算,可能会造成页面真实底部位置超出屏幕范围的情况,left、right同理。
extras:新窗口的额外扩展参数,可用来处理页面间传值;例如:
var webview = mui.openWindow({
url:'info.html',
extras:{
name:'mui'
}
});
console.log(webview.name);
控制台会输出"mui"字符串;
注意:扩展参数仅在打开新窗口时有效,若目标窗口为预加载页面,则通过mui.openWindow方法打开时传递的extras参数无效。
createNew:是否重复创建相同id的webview;为优化性能、避免app中重复创建webview,mui v1.7.0开始增加createNew参数,默认为false;判断逻辑如下:若createNew为true,则不判断重复,每次都新建webview;若为fasle,则先计算当前App中是否已存在同样id的webview,若存在则直接显示;否则新创建并根据show参数执行显示逻辑;该参数可能导致的影响:若业务写在plusReady事件中,而plusReady事件仅首次创建时会触发,则下次再次通过mui.openWindow方法打开同样webview时,是不会再次触发plusReady事件的,此时可通过自定义事件触发;案例参考:http://ask.dcloud.net.cn/question/6514;
**show:**表示窗口显示控制。autoShow:目标窗口loaded事件发生后,是否自动显示;若目标页面为预加载页面,则该参数无效;aniShow表示页面显示动画,比如从右侧划入、从下侧划入等,具体可参考5+规范中的AnimationTypeShow。
waiting:表示系统等待框;mui框架在打开新页面时等待框的处理逻辑为:显示等待框–>创建目标页面webview–>目标页面loaded事件发生–>关闭等待框;因此,只有当新页面为新创建页面(webview)时,会显示等待框,否则若为预加载好的页面,则直接显示目标页面,不会显示等待框。waiting中的参数:autoShow表示自动显示等待框,默认为true,若为false,则不显示等待框;注意:若显示了等待框,但目标页面不自动显示,则需在目标页面中通过如下代码关闭等待框plus.nativeUI.closeWaiting();。title表示等待框上的提示文字,options表示等待框显示参数,比如宽高、背景色、提示文字颜色等,具体可参考5+规范中的WaitingOption。
示例1:Hello mui中,点击首页右上角的图标,会打开关于页面,实现代码如下:
//tap为mui封装的单击事件,可参考手势事件章节
document.getElementById(‘info’).addEventListener(‘tap’, function() {
//打开关于页面
url: 'examples/info.html',
id:'info'
});
});
因没有传入styles参数,故默认全屏显示;也没有传入show参数,故使用slide-in-right动画,新页面从右侧滑入。
示例2:从A页面打开B页面,B页面为一个需要从服务端加载的列表页面,若在B页面loaded事件发生时就将其显示出来,因服务器数据尚未加载完毕,列表页面为空,用户体验不好;可通过如下方式改善用户体验(最好的用户体验应该是通过预加载的方式)
第一步,B页面loaded事件发生后,不自动显示
//A页面中打开B页面,设置show的autoShow为false,则B页面在其loaded事件发生后,不会自动显示;
mui.openWindow({
url: 'B.html',
show:{
autoShow:false
}
});
第二步,在B页面获取列表数据后,再关闭等待框、显示B页面
//B页面onload从服务器获取列表数据;
window.onload = function(){
//从服务器获取数据
....
//业务数据获取完毕,并已插入当前页面DOM;
//注意:若为ajax请求,则需将如下代码放在处理完ajax响应数据之后;
mui.plusReady(function(){
//关闭等待框
plus.nativeUI.closeWaiting();
//显示当前页面
mui.currentWebview.show();
});
}
关闭页面
mui框架将窗口关闭功能封装在mui.back方法中,具体执行逻辑是:
若当前webview为预加载页面,则hide当前webview;否则,close当前webview。
在mui框架中,有三种操作会触发页面关闭(执行mui.back方法)。
点击包含.mui-action-back类的控件
在页面上,向右快速滑动
Android手机按下back按键
hbuilder中敲mheader生成的代码块,会自动生成带有返回导航箭头的标题栏,点击返回箭头可关闭当前页面,原因就是因为该返回箭头包含.mui-action-back类,代码如下:
<header class="mui-bar mui-bar-nav">
<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
<h1 class="mui-title">标题</h1>
</header>
若希望在顶部导航栏之外的其它区域添加关闭页面的控件,只需要在对应控件上添加.mui-action-back类即可,如下为一个关闭按钮示例:
<button type="button" class='mui-btn mui-btn-danger mui-action-back'>关闭</button>
mui框架封装的页面右滑关闭功能,默认未启用,若要使用右滑关闭功能,需要在mui.init();方法中设置swipeBack参数,如下:
mui.init({
swipeBack:true //启用右滑关闭功能
});
mui框架默认会监听Android手机的back按键,然后执行页面关闭逻辑; 若不希望mui自动处理back按键,可通过如下方式关闭mui的back按键监听;
mui.init({
keyEventBind: {
backbutton: false //关闭back按键监听
}
});
除了如上三种操作外,也可以直接调用mui.back()方法,执行窗口关闭逻辑;mui.back()仅处理窗口逻辑,若希望在窗口关闭之前再处理一些其它业务逻辑,则可将业务逻辑抽象成一个具体函数,然后注册为mui.init方法的beforeback参数;beforeback的执行逻辑为:
执行beforeback参数对应的函数若返回false,则不再执行mui.back()方法;否则(返回true或无返回值),继续执行mui.back()方法;
示例:从列表打开详情页面,从详情页面再返回后希望刷新列表界面,此时可注册beforeback参数,然后通过自定义事件通知列表页面刷新数据,示例代码如下:
mui.init({
beforeback: function(){
//获得列表界面的webview
var list = plus.webview.getWebviewById('list');
//触发列表界面的自定义事件(refresh),从而进行数据刷新
mui.fire(list,'refresh');
//返回true,继续页面关闭逻辑
return true;
}
});
注意:beforeback的执行返回必须是同步的(阻塞模式),若使用nativeUI这种异步js(非阻塞模式),则可能会出现意想不到的结果;比如:通过plus.nativeUI.confirm()弹出确认框,可能用户尚未选择,页面已经返回了(beforeback同步执行完毕,无返回值,继续执行mui.back()方法,nativeUI不会阻塞js进程):在这种情况下,若要自定义业务逻辑,就需要复写mui.back方法了;如下为一个自定义示例,每次都需要用户确认后,才会关闭当前页面。
//备份mui.back,mui.back已将窗口关闭逻辑封装的比较完善(预加载及父子窗口),因此最好复用mui.back
var old_back = mui.back;
mui.back = function(){
var btn = ["确定","取消"];
mui.confirm('确认关闭当前窗口?','Hello MUI',btn,function(e){
if(e.index==0){
//执行mui封装好的窗口关闭逻辑;
old_back();
}
});
}
注意:自定义关闭逻辑时,一定要重写mui.back,不能简单通过addEventListener增加back按键监听, 因为addEventListener只会增加新的执行逻辑,老的监听逻辑依然会执行;
底部导航栏
方案一:在plus环境下使用原生titleNView以及原生tabbar来替换也买呢的导航栏或者选项卡,页面打开时渲染已经完成
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello MUI</title>
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet" href="css/mui.min.css">
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 id="title" class="mui-title">首页</h1>
</header>
<nav class="mui-bar mui-bar-tab">
<a class="mui-tab-item mui-active" href="home.html">
<span class="mui-icon mui-icon-home"></span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" href="video.html">
<span class="mui-icon mui-icon-email"><span class="mui-badge">9</span></span>
<span class="mui-tab-label">视频</span>
</a>
<a class="mui-tab-item" href="data.html">
<span class="mui-icon mui-icon-contact"></span>
<span class="mui-tab-label">数据</span>
</a>
<a class="mui-tab-item" href="me.html">
<span class="mui-icon mui-icon-gear"></span>
<span class="mui-tab-label">我的</span>
</a>
</nav>
<div class="mui-content"></div>
<script src="js/mui.min.js"></script>
<script type="text/javascript" charset="utf-8">
/*浏览器的兼容处理方法*/
var createIframe = function (el, opt) {
var elContainer = document.querySelector(el);
var wrapper = document.querySelector(".mui-iframe-wrapper");
if(!wrapper){
// 创建wrapper 和 iframe
wrapper = document.createElement('div');
wrapper.className = 'mui-iframe-wrapper';
for(var i in opt.style){
wrapper.style[i] = opt.style[i];
}
var iframe = document.createElement('iframe');
iframe.src = opt.url;
iframe.id = opt.id || opt.url;
iframe.name = opt.id;
wrapper.appendChild(iframe);
elContainer.appendChild(wrapper);
}else{
var iframe = wrapper.querySelector('iframe');
iframe.src = opt.url;
iframe.id = opt.id || opt.url;
iframe.name = iframe.id;
}
}
// mui初始化
mui.init();
var subpages = ['home.html', 'video.html', 'data.html', 'me.html'];
var subpage_style = {
top: '45px',
bottom: '51px'
};
var aniShow = {};
// 当前激活选项
var activeTab = subpages[0];
var title = document.getElementById("title");
if(mui.os.plus){
// 创建子页面,首个选项卡页面显示,其它均隐藏;
mui.plusReady(function() {
var self = plus.webview.currentWebview();
for (var i = 0; i < 4; i++) {
var temp = {};
var sub = plus.webview.create(subpages[i], subpages[i], subpage_style);
if (i > 0) {
sub.hide();
}else{
temp[subpages[i]] = "true";
mui.extend(aniShow,temp);
}
self.append(sub);
}
});
}else{
// 创建iframe代替子页面
createIframe('.mui-content',{
url: activeTab,
style: subpage_style
});
}
// 选项卡点击事件
mui('.mui-bar-tab').on('tap', 'a', function(e) {
var targetTab = this.getAttribute('href');
if (targetTab == activeTab) {return;}
//更换标题
title.innerHTML = this.querySelector('.mui-tab-label').innerHTML;
//显示目标选项卡
if(mui.os.plus){
//若为iOS平台或非首次显示,则直接显示
if(mui.os.ios||aniShow[targetTab]){
plus.webview.show(targetTab);
}else{
//否则,使用fade-in动画,且保存变量
var temp = {};
temp[targetTab] = "true";
mui.extend(aniShow,temp);
plus.webview.show(targetTab,"fade-in",300);
}
//隐藏当前;
plus.webview.hide(activeTab);
}else{
// 创建iframe代替子页面
createIframe('.mui-content',{
url: targetTab,
style: subpage_style
});
}
//更改当前活跃的选项卡
activeTab = targetTab;
});
</script>
</body>
</html>
方案二:通过双webview模式解决,此种情况适用于需要上下拉刷新的列表页面。将需要滚动的区域通过单独的webview实现,完全使用原生滚动。具体做法则是:将目标页面分解为主页面和内容页面,主页面显示卡头卡尾区域,比如顶部导航、底部选项卡等;内容页面显示具体需要滚动的内容,然后在主页面中调用mui.init方法初始化内容页面
概念澄清
HBuilder8.0.1版更新说明App中有一条:
**【重要】**新增双首页配置(manifest->plus->secondwebview),加速首页为双webview模式时的应用启动速度。
以往流应用或5+App的首页,就是指的入口页面这一个页面,应用启动时native层立即创建这个launchWebview。
双首页配置下,入口页面依旧是launchWebview,但是还有一个secondWebview同时被创建。两个webview的操作由native层完成,大大提高了第二个webview的创建及加载速度。
举例说明
常规方案
以首页父子页面结构为例,子页面的创建在父页面(即首页)中完成。
var launch = plus.webview.getLaunchWebview();
var home = plus.webview.create('home.html','home', {
top: '50px',
bottom: 0
});
launch.append(home);
创建子页面这个操作,需要在首页加载完成后才开始。这样就会造成用户先看到首页部分的内容,然后才能看到子页面的内容。
双首页模式
依照更新说明,在manifest.json文件的plus节点下,新增secondwebview节点配置。
`
"plus": {
"secondwebview": {
"launch_path": "home.html",
"id": "home"
}
}
这里同样支持secondWebview的styles等属性。
"plus": {
"secondwebview": {
"launch_path": "home.html",
"id": "home",
"top": "50px",
"bottom": "0px"
}
}
然后,在launchWebview中建立父子关系即可。当然,如果非必要情况下,是不用建立父子关系的。
var _self = plus.webview.getLaunchWebview();
var _second = plus.webview.getSecondWebview();
_self.append(_second);
在双首页模式下,父页面和子页面的内容是同时显示的,不会给用户造成加载延迟的感觉,大大增强了流应用及5+App的体验。
div方案div方案的选项卡是普通的实现方案,所有都放在一个页面中执行,页面压力可想而知,在手机上会出现卡顿现象。SPA仅适用于非常简单的dom和非常少的页面;
无语到不行的div+div没贴代码
算了官方文档读起来很难,我十分混乱,后边慢慢整理
引导欢迎页面
Swiper触摸滑动组件(开源)
swiper官网
Swiper 的结构和基础原理
Swiper 的每个展示块(屏)为一个slide,slide中放置图片或文字等展示的内容,全部slide排成一行(或多行)包含在包装器wrapper中,而总容器container 又包裹着wrapper和箭头按钮控件navigation以及分页器控件pagination。
当手指(或鼠标)触摸滑动Swiper时,Swiper在浏览器每一帧通过计算滑动的距离差对wrapper进行位移(transform)从而产生拖动的效果。在手指(或鼠标)释放时,计算下一个slide的起始位置对wrapper设置位移动画(transition),从而产生切换动画效果。
使用方法
1.首先加载插件,需要用到的文件有swiper.min.js和swiper.min.css文件。可下载Swiper文件或使用CDN。
<!DOCTYPE html>
<html>
<head>
...
<link rel="stylesheet" href="dist/css/swiper.min.css">
</head>
<body>
...
<script src="dist/js/swiper.min.js"></script>
...
</body>
</html>
2.HTML内容。
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
<!-- 如果需要导航按钮 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- 如果需要滚动条 -->
<div class="swiper-scrollbar"></div>
</div>
导航等组件可以放在container之外
3.你可能想要给Swiper定义一个大小,当然不要也行。
.swiper-container {
width: 600px;
height: 300px;
}
4.初始化Swiper:最好是挨着标签
<script>
var mySwiper = new Swiper ('.swiper-container', {
direction: 'vertical', // 垂直切换选项
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// 如果需要滚动条
scrollbar: {
el: '.swiper-scrollbar',
},
})
</script>
</body>
如果不能写在HTML内容的后面,则需要在页面加载完成后再初始化。
<script>
window.onload = function() {
...
}
</script>
或者这样(Jquery和Zepto)(推荐)
<script>
$(document).ready(function () {
...
})
</script>
5.完成。恭喜你,现在你的Swiper应该已经能正常切换了。
如果作为CommonJs 或ES 模块引入
//CommonJs
var Swiper = require('swiper');
var mySwiper = new Swiper('.swiper-container', { /* ... */ });
//ES
import Swiper from 'swiper';
var mySwiper = new Swiper('.swiper-container', { /* ... */ });
动态加载解决app重启时候缓存问题
var app_config = {
version: '1.0.0',
cssAr: [],
jsAr: []
}
// 动态加载解决app重启时候缓存问题。
Array.prototype._distinct = function() {
var arr = this,
result = [],
_result = [],
len = arr.length;
arr.forEach(function(v, i, arr) {
var _v = v.split('/')[v.split('/').length - 1];
if(_result.indexOf(_v) === -1) {
result.push(v);
_result.push(_v);
} else {
//替换默认引入文件
result[_result.indexOf(_v)] = v;
_result[_result.indexOf(_v)] = _v;
}
})
return result;
};
function link(cssAr, type) {
var cssAr = type ? cssAr._distinct() : app_config.cssAr.concat(cssAr || [])._distinct();
for(var i = 0; i < cssAr.length; i++) {
document.write('<link rel="stylesheet" href="' + cssAr[i] + '?version=' + app_config.version + '"/>');
}
}
function script(jsAr, type) {
var jsAr = type ? jsAr._distinct() : app_config.jsAr.concat(jsAr || [])._distinct();
for(var i = 0; i < jsAr.length; i++) {
document.write('<script src="' + jsAr[i] + '?version=' + app_config.version + ' type="text/javascript" charset="utf-8"><\/script>');
}
}
引导函数
<script type="text/javascript">
//打开引导
var firstGuide = localStorage.getItem("guide");
if(firstGuide != "yes"){
window.location.href='hello.html'; //启动引导页
}
</script>
来源:CSDN
作者:abolition cc
链接:https://blog.csdn.net/weixin_45338913/article/details/104625307