创建单页工程
使用buijs命令行构建.
目前 >>我<< 只通过这种方式 使用 buijs命令行 创建demo成功过,其他暂无成功!
创建demo工程:
# 创建目录
$ mkdir demo
# 进入demo目录
$ cd demo
# 创建单页工程
$ buijs create
安装依赖及预览:
# 安装工程依赖
$ npm install
# 运行服务并预览
$ npm run dev
部分服务如下:
Local: http://localhost:3819
External: http://192.168.1.2:3819
------------------------------------
UI: http://localhost:3820
UI External: http://192.168.1.2:3820
------------------------------------
[Browsersync] Serving files from: dist
目录说明:
目录名 | 描述 | 是否必须 |
---|---|---|
/app.json | 插件及跨域的配置 | 否 |
/gulpfile.js | gulp编译配置 | 否 |
/package.json | 工程依赖配置 | 否 |
/src/index.html | 应用首页入口文件 | 是 |
/src/index.js | 路由的初始化脚本及全局事件 | 是 |
/src/css/ | 应用样式及bui.css样式 | 是 |
/src/font/ | bui.css用到的字体图标 | 是 |
/src/images/ | 应用图片目录 | 否 |
/src/js/ | 应用脚本 | 是 |
/src/js/zepto.js | bui.js默认依赖于zepto.js 或 jquery | 是 |
/src/js/bui.js | BUI交互控件库 | 是 |
/src/pages/ | 应用的模块 | 是 |
/src/pages/main/ | 默认路由初始化以后会先载入这个main模块 | 是 |
/src/pages/main/main.html | main模块的模板 | 是 |
/src/pages/main/main.js | main模块的业务脚本 | 是 |
路由初始化
打开编辑 src/index.html , body 下只有一个div,这个便是路由最外层结构.
src/index.html
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>BUI单页工程</title>
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<link rel="stylesheet" href="css/bui.css" />
</head>
<body>
<!-- 第1步: 开启单页路由 -->
<div id="bui-router"></div>
<script src="js/zepto.js"></script>
<script src="js/bui.js"></script>
<!-- 初始化单页 -->
<script src="index.js"></script>
</body>
</html>
src/index.js
// 把路由实例化给 window.router
window.router = bui.router();
bui.ready(function(){
// 加载页面到div容器里面, 更多参数请查阅API
router.init({
id: "#bui-router"
})
})
当路由初始化以后,
会自动查找首页main模块, 这个模块是内部定义好的,
默认指向路径 pages/main/main.html 并自动加载相同名字的js文件.
除了main, 正常我们都是创建匿名模块,这样只要通过路径跳转,就会自动加载同名的脚本.
main模块
src/pages/main/main.html:
<div class="bui-page">
<header class="bui-bar">
<div class="bui-bar-left">
</div>
<div class="bui-bar-main">main</div>
<div class="bui-bar-right">
</div>
</header>
<main>
<div id="btn" class="bui-btn">跳转page2.html</div>
</main>
<footer></footer>
</div>
src/pages/main/main.js
loader.define(function(require,exports,module){
// 绑定按钮跳转
$("#btn").on("click",function(){
router.load({ url: "pages/page2/page2.html", param: {} });
})
})
pages/page2/page2模块
我们再创建一个 src/pages/page2/page2.html,及 src/pages/page2/page2.js ,那通过下面的方式跳转,则创建了一个 src/pages/page2/page2 的模块.
src/pages/page2/page2.html
<div class="bui-page">
<header class="bui-bar">
<div class="bui-bar-left">
</div>
<div class="bui-bar-main">page2</div>
<div class="bui-bar-right">
</div>
</header>
<main></main>
<footer></footer>
</div>
src/pages/page2/page2.js
loader.define(function(require,exports,module){
// 脚本都需要在这里执行
})
注意:
- 页面已经加载过,应该使用后退操作, 例如,上面的例子,在pages2.html,不要使用
router.load({url:”main”}) 这样跳回首页, 使用 router.back;`
路由原理
页面跳转
router.load(option)
页面跳转,保持js跟html一致的命名,才能自动加载触发. 同样支持 bui.btn 静态跳转
router.load({ url: "pages/page2/page2.html", param: {} });//param:传给目标页面的参数
接收参数
router.getPageParams
接收到的参数为一个对象, 无需在回调里面拿.
var params = router.getPageParams();
页面后退
router.back(option)
支持后退以后执行回调,具体查看bui.back API
// 普通后退
router.back();
// 后退2层刷新
router.back({
index: -2,
callback: function(){
router.refresh()
}
});
// 后退局部刷新
router.back({
callback: function(module){
// 后退的页面有抛出一个init方法
module.init();
}
});
// 不管在哪层,都可以后退到首页
router.back({
name: "main"
});
页面刷新
router.refresh
页面刷新有可能造成事件重复绑定, 所以一般不建议这样使用. 可以结合 loader.require 调用模块抛出的方法, 实现局部刷新功能.
router.refresh();
页面替换
router.replace(option)
页面替换不会增加历史记录
router.replace({ url: "pages/page3/page3.html" });
局部加载模块
router.loadPart
router.loadPart({ id:"#part", url: "pages/page2/page2.html", param: {} });
//id:局部的id或者对象
//url:相对路径
//param:传给目标页面的参数
局部接收参数
router.getPartParams(moduleName)
//moduleName:模块的名称
loader.define(function(require,exports,module) {
// module 为当前的模块信息
var pid = module.moduleName,
params = router.getPartParams(pid);
})
预加载
router.preload(option)
如果你的应用是webapp,那这个功能就比较好用了,先在首页预加载想要触发的页面, 当点击触发相同页面的时候, 你会发现跳转速度快多了, 本地应用则无需使用到预加载
//url:缓存模板
//script:缓存脚本
// 预加载一个页面
router.preload({ url: "pages/page2/page2.html" });
// 预加载多个页面
router.preload([{
url: "pages/page2/page2.html"
},{
url: "pages/page3/page3.html"
}]);
获取当前页面dom对象
router.currentPage()
// 获取当前页面唯一ID
var currentPage = router.currentPage();
页面需要重复加载
router. 替换 替 换
router.
跟
跟
的区别在于,
router.
是相对于当前页面查找,有一种情况,页面需要被重复加载,比方列表页,跳转到详情页,详情页又有推荐的列表,点击又会跳转到详情,这种时候,
是
相
对
于
当
前
页
面
查
找
,
有
一
种
情
况
,
页
面
需
要
被
重
复
加
载
,
比
方
列
表
页
,
跳
转
到
详
情
页
,
详
情
页
又
有
推
荐
的
列
表
,
点
击
又
会
跳
转
到
详
情
,
这
种
时
候
,
绑定页面的事件会被重复绑定, router.$ 则不会.
// 绑定当前页面下样式为 btn 的事件
router.$(".bui-page").on("click",".btn",function(e){
})
另外,建议一个单页应用的层级建议控制在 5级左右. 已经加载过的页面,使用后退刷新处理. 例如:
// 推荐: 这也是微信小程序里面推荐的层级数
A->B->C->D->E
// 不要这样, 这种做法本身会让用户陷入混乱
A->B->C->B->C
获取历史记录
router.history.get()
获取当前路由的历史记录
var routerHistory = router.history.get();
router.history.getLast()
获取路由的最后一条记录
var routerLastHistory = router.history.getLast();
路由全局事件
load 事件
页面加载,在模板加载完成就会触发,有缓存的时候只触发一次
router.on("load",function(e){
// 获取当前页的模块
console.log(e.currentTarget);
// 获取上一页的模块
console.log(e.prevTarget);
})
complete 事件
页面完成,每次加载完模板都会触发
router.on("complete",function(e){
// 获取当前页的模块
console.log(e.currentTarget);
// 获取上一页的模块
console.log(e.prevTarget);
})
back 事件
router.on("back",function(e){
// 获取当前页的模块
console.log(e.currentTarget);
// 获取上一页的模块
console.log(e.prevTarget);
})
refresh 事件
router.on("refresh",function(e){
// 获取当前页的模块
console.log(e.currentTarget);
// 获取上一页的模块
console.log(e.prevTarget);
})
loadpart 事件
页面局部加载后触发
router.on("loadpart",function(e){
// 获取当前页子模块
console.log(e.currentTarget);
// 获取当前页父模块
console.log(e.prevTarget);
})
index.js
bui.ready(function(){
// 执行事件绑定
bind();
})
function bind(){
// 静态绑定 bui-router 容器下所有带有 href 属性的按钮, 点击就会自动跳转, 一个单页应用只需要初始化一次.
bui.btn({id:"#bui-router",handle:".bui-btn"}).load();
// 监听页面所有后退事件
router.on("back",function(e){
console.log(e);
})
}
注意: 建议全局事件都在 index.js 加载. 事件名全部为小写.