Framework7介绍
(1)Framework7 是一个开源免费的框架。可以用来开发混合移动应用(原生和 HTML 混合)或者开发 iOS & Android 风格的 WEB APP。也可以用来作为原型开发工具,可以迅速创建一个应用的原型。
(2)使用时只需要一个基本的 HTML 布局,并且把 Framework7 的 CSS 和 JS 文件引入即可!Framework7 不会强制你写任何自定义的标签,也不会通过 JS 来生成任何额外的内容。你不需要通过 JS 或者 JSON 来写页面,只需要普通的 HTML 就可以。
(3)Framework7 有大量可以直接使用的 UI 组件和工具,比如导航栏、侧边栏、弹出层、标签页、虚拟列表、日期控件、手风琴等。大部分的组件你都完全不需要写任何 JS 代码。
一、页面结构
拿到原型图:
Framework7标签栏应用案例:http://examples.framework7.cn/tab-bar/
一开始看到原型图和F7里面的这个案例,果断就把案例直接下载来使用。交给后台开发时被告知“没达到开发要求”,原因:
标签栏应用案例结构:
标签页是一个页面,不方便控制和后期维护。于是切分成四个页面,在点击底部导航栏时按需加载进来。
修改后的页面结构如下:
index.html
其它页面 xxx.html
默认情况下 Framework7 会使用 Ajax 加载所有的页面,当我们触发切换页面的事件时,Framework7会通过Ajax获取 xxx.html,解析它的内容,然后把它插入到DOM中,并且做一个动画切换到这个新页面。
因为Framework7有一个非常聪明的解析器,所以在内部页面中我们不需要完整的HTML结构(head,body,views,pages等)。Framework7 解析器会尝试在ajax加载的页面中寻找 Template7是framework7的内置模板引擎,无需包含额外的 JS 文件。 type="text/template7" 指定了这个script的内容会被 Framework7 当做一个 Template7 模板自动编译 id="myTemplate" 是模板的id,后面可以通过这个id来找到这个模板 你需要在 初始化应用 的时候传入一个参数来启用自动编译模板功能: 渲染: Framework7 可以使用 Template7 用特定的上下文来渲染ajax页面或者动态页面,并且提供了很多不同的方法来实现. 首先,我们需要在 应用初始化 的时候传入一个参数来开启这个功能: xxx.html Hello, my name is {{name}} and i am {{age}} years old {{position}} at {{company}} 模板页面数据: ajax传入数据: 使用情况: 遇到的问题: 解决: 虚拟列表可以用来渲染有大量数据的列表,并且不有有任何的性能问题。并且,它和所有的Framework7组件都是兼容的,包括搜索栏、无限滚动、下拉刷新、滑动删除和可排序列表。 在页面中放一个空的虚拟列表容器 使用Template7模板渲染: Framework7主要有两个切换页面的方法: mainView.router.load(options) - 把一个页面加载到当前视图 mainView.router.back(options) - 这个方法会触发一个反向的动画并回到上一个页面,也就是浏览历史上的回退 主要使用到的参数: 遇到的问题: 解决: 在产品页面有一个“下拉加载数据”的需求,F7有一个“无限滚动”组件,即列表滚动到底部时触发加载函数。最初使用的是这个组件,使用方法: 给div.page-content加上infinite-scroll类 初始化“无限滚动”组件 每一次滚动到底部都会执行回调函数里的代码 遇到的问题: 解决:优化DOM结构,div.page-content一开始就要在页面中存在。 解决:所有tab栏分类公用一个虚拟列表,切换tab页面时清空当前列表,重新加载指定数据。 解决:给一个固定高度。 解决:在虚拟列表下新增一个DOM容器,用来加载图片。图片的容器下新增一个虚拟列表容器,装其它类别的数据。 解决:使用iScroll5插件。 rem是相对于根元素 例如: div的宽 = 6*20 = 120px 使用: 计算规则: 遇到的问题: 部分安卓机型对rem支持不是很好,出现布局错位问题。 文本的字号使用rem会出现小屏字体太小,大屏字体太大的情况 通常我们js写在一个或多个文件里,用 并且js的加载会阻塞页面渲染,而且由于js文件之间存在依赖关系,必须严格保证加载顺序,依赖性最大的模块一定要放到最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。 require.Js就是为了解决以上问题。 使用: 创建一个main.js 然后在页面中使用下面的方式来使用requirejs: data-main属性的作用是,指定网页程序的主模块。在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。 require会定义三个变量:define,require,requirejs,其中require === requirejs,一般使用require更简短 define 从名字就可以看出这个api是用来定义一个模块 例: 如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性。 当require()函数加载上面这个模块的时候,就会先加载myLib.js文件。 加载方法如下: 理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合。那么,require.js怎样加载非规范的模块呢? 这样的模块在用require()加载之前,要先用require.config()方法,定义它们的一些特征。 require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义(1)exports值(输出的变量名),表明这个模块外部调用时的名称;(2)deps数组,表明该模块的依赖性。 比如,jQuery的插件可以这样定义: 遇到的问题:二、Template7 模板
1. 自动编译模板
var myApp = new Framework7({
precompileTemplates: true, // 启用模板
});
var Html = Template7.templates.broadTemplate(data);
$$('div').html(Html);
2. 模板页面
var myApp = new Framework7({
template7Pages: true, // 模板页面
});
var myApp = new Framework7({
template7Pages: true,
template7Data: {
'url:xxx.html': {
name: 'John Doe',
age: 38,
company: 'Apple',
position: 'Developer'
},
}
});
ajax_json({
url: url,
success: function(data){
mainView.router.load({
url: "xxx.html",
context: data.result
})
}
});
自动编译模板
在模板页面有多个数据源的时候,不能结合自动编译模板同时使用(表达式混淆。除非把模板放在首页)。
列表模块使用F7自带的虚拟列表组件进行动态渲染。3. 虚拟列表
var myList = myApp.virtualList('.list-block.virtual-list', {
items: data,
template: '
三、页面切换
url:需要加载的页面的URL
context:渲染Template7 模板时需要的上下文(模板数据)。
query:页面路由传递的参数
force:只对 back 方法有效。如果设置为 true,那么会忽略浏览历史中的上一个页面,而是直接加载指定的页面。
reload:如果设置为 true,那么不会当做新页面加载,而是直接替换当前视图的当前页面。并且在视图浏览历史中替换最后一条历史。
在一个页面更改了数据后,使用back回退到上个页面,页面数据没有刷新mainView.router.back({
url: url, // 指定回退页面的url
context: data, // 传递模板数据给指定加载的页面
force: true // 设置为true,直接加载指定的页面
});
四、滚动加载
$$('.infinite-scroll').on('infinite', function () {
// code...
});
五、其它
1. Rem适配问题
,这样就意味着,我们只需要在根元素确定一个px字号,则可以来算出元素的宽高。
html{
font-size:20px;
}
div {
width: 6rem;
height: 3rem;
}
html {
font-size : 20px;
}
@media only screen and (min-width: 401px){
html {
font-size: 25px !important;
}
}
@media only screen and (min-width: 428px){
html {
font-size: 26.75px !important;
}
}
@media only screen and (min-width: 481px){
html {
font-size: 30px !important;
}
}
@media only screen and (min-width: 569px){
html {
font-size: 35px !important;
}
}
@media only screen and (min-width: 641px){
html {
font-size: 40px !important;
}
}
function tryResize(){
var docEl=document.documentElement;
var clientHeight = docEl.clientWidth;
if(!clientHeight)
{
return
}
docEl.style.fontSize=20*(clientHeight/375)+"px"
}
tryResize();
window.onresize=tryResize;
例如设计稿是375的尺寸,375页面的font-size是20px,那么320的页面呢?320/375 = 0.8533 320是375的0.8533倍,所以320的font-size等于20*0.8533 = 17.0667。
解决:根据实际情况来考虑元素是运用rem单位还是百分比或者是flex弹性布局。
解决:文本字号使用px单位,结合媒体查询2. 使用require.Js管理js文件
标签引入页面,但js文件过多会出现以下丑陋场景:
// async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。
require.config({
paths : { // 引用路径
"jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery", "js/jquery"],
"a" : "js/a"
}
})
require 加载依赖模块,并执行加载完后的回调函数// a.js
define(function (){
var add = function (x,y){
return x+y;
};
return {
add: add
};
});
define(['myLib'], function(myLib){
function foo(){
myLib.doSomething();
}
return {
foo : foo
};
});
// main.js
require(['a'], function (a){
alert(a.add(1,1));
});
require.config({
shim: {
'jquery.scroll': {
deps: ['jquery'], // 依赖的模块
exports: 'jQuery.fn.scroll' // 输出的变量名
}
}
});
使用百度的WebUploader上传组件时,报错找不到 WebUploader 变量。
原因: cdn版本较低
解决: 官网下载最新版