移动端推广速度快,效果好,越来越多的企业,商家开始重视移动站的建设和移动页面(h5)的制作。随着移动页面的玩法越来越多,对前端技术的要求也会越来越高。
关于移动设备一些基本概念的理解。
网站示例
网址:https://github.com/amfe/lib-flexible;
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
html与css:
<!DOCTYPE html>
</html>
JS:
var waterfall = function(wrap, boxes) {
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
/* 标签重定义 */
* {
margin: 0;
padding: 0;
border: none;
}
body {
background: #ddd;
}
img {
border: none;
}
a {
text-decoration: none;
color: #444;
}
a:hover {
color: #999;
}
/* wrap */
#wrap {
position: relative;
width: auto;
height: auto;
margin: 0 auto;
}
#wrap>div {
float: left;
box-sizing: border-box;
width: 280px;
height: auto;
margin: 10px;
padding: 10px;
border-radius: 5px;
background: #fff;
}
#wrap>div>img {
width: 260px;
margin: 0 auto;
}
#wrap>div>a {
display: block;
font-size: 18px;
font-weight: bold;
line-height: 40px;
text-align: center;
}
</style>
</head>
<body>
<div id="wrap">
<div>
<img src="img/1.jpg">
<a href="http://www.imooc.com" target="_blank">第一张 路飞与艾斯</a>
</div>
<div>
<img src="img/2.jpg">
<a href="http://www.imooc.com" target="_blank">第二张 艾博</a>
</div>
<div>
<img src="img/3.jpg">
<a href="http://www.imooc.com" target="_blank">第三张 路飞</a>
</div>
<div>
<img src="img/4.jpg">
<a href="http://www.imooc.com" target="_blank">第四张 艾斯</a>
</div>
<div>
<img src="img/5.jpg">
<a href="http://www.imooc.com" target="_blank">第五张 女王</a>
</div>
<div>
<img src="img/6.jpg">
<a href="http://www.imooc.com" target="_blank">第六张 香吉士</a>
</div>
<div>
<img src="img/7.jpg">
<a href="http://www.imooc.com" target="_blank">第七张 艾斯</a>
</div>
<div>
<img src="img/8.jpg">
<a href="http://www.imooc.com" target="_blank">第八张 霸气</a>
</div>
</div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/script.js"></script>
</body>
// 获取屏幕可以显示的列数
var boxWidth = boxes.eq(0).width() + 40;
var windowWidth = $(window).width();
var colsNumber = Math.floor(windowWidth / boxWidth);
// 设置容器的宽度
wrap.width(boxWidth * colsNumber);
// 定义一个数组并存储每一列的高度
var everyHeight = new Array();
for (var i = 0; i < boxes.length; i++) {
if (i < colsNumber) {
everyHeight[i] = boxes.eq(i).height() + 40;
} else {
var minHeight = Math.min.apply(null, everyHeight);
var minIndex = getIndex(minHeight, everyHeight);
boxes.eq(i).css({
'position': 'absolute',
'top': minHeight,
'left': boxes.eq(minIndex).position().left,
'opacity': '0'
}).stop().animate({
'opacity': '1'
}, 1000);
everyHeight[minIndex] += boxes.eq(i).height() + 40;
};
}
};
// 获取最小列的索引
function getIndex(minHeight, everyHeight) {
for (index in everyHeight) {
if (everyHeight[index] == minHeight) {
return index;
};
};
};
$(document).ready(function(event) {
var wrap = $('#wrap');
var boxes = $('#wrap').children('div');
waterfall(wrap, boxes);
});
1.Json的格式
其实json就是对象。源生的js代码并没有类的概念。对象救就是object。对象有自己的属性,也可以有自己的方法。json是一种轻量级的存储和交换信息的语言。他有自己的格式。
较为简单的json。里面只有简单的对象,key+value的形式:
每个元素之间用逗号隔开。调用每个key的值可用语句。例如:CellInfo.UEAmunt,就可取出其中的值。
较为复杂的json。里面包含了对象。
例如这个UEGroup1,里面的元素不仅有简单的key+value,还包含了三个对象。对象里的元素用{}括起来,彼此之间用逗号隔开。想具体访问某个元素的值也是通过逐层key,例如:UEGrooup1.DBR1.DLPackageSize
动态的往json只增加元素,增加对象。
前面说的几个都是静态的,提前写好的。那如果临时想加一个元素,例如在Cellinfo这个json中相加一个number的元素:
CellInfo.number=10;
对于往json中添加对象。例如我们想把Cellinfo和UEGroup1这两个object作为两个元素加入到另外一个大的json中:
2.json的发送
json写好后,发送给后台。至于后台怎么处理数据我们不关心。发送json的函数如下:
}
参数分别是后台的地址,变量,方法。变量就是我们自己写好的json,方法默认为post。例如我们想发刚刚的PETInfo
$.post('http://10.140.160.64:3012/users/ueinfo', PETInfo);
数据的发送、并获取结果的实例:
需求描述:用户填写一系列的输入框,前端获取数据,封装成json并发送给服务器,服务器会返回一个返回值,表示状态。前端需要展示这个内容提示客户。
3.json在本地的存储
存储数据有很多方法。这里我用的是localStorage。localStorage与cookie的区别如下:
① cookie在浏览器与服务器之间来回传递。
sessionStorage和localStorage不会把数据发给服务器,仅在本地保存
②数据有效期不同:
cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
sessionStorage:仅在当前浏览器窗口关闭前有效。
localStorage 始终有效,长期保存。
③cookie数据还有路径的概念,可以限制cookie只属于某个路径下。
存储大小也不同,cookie数据不能超过4k,sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
④ 作用域不用
sessionStorage不在不同的浏览器窗口中共享;
localStorage在所有同源窗口中都是共享的;
cookie也是在所有同源窗口中都是共享的;
WebStorage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便。
用localstage存储json的实例:
将json取出来:
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
控制表格的多选和反选,直接上代码,顺便安利一个小知识点:tr的底边框不显示的问题,解决办法是:table{border-collapse:collapse;}
-
<!DOCTYPE html>
-
<html>
-
<head>
-
<title></title>
-
<style>
-
*{margin:0;padding:0;}
-
table{border-collapse:collapse}
-
.detail_tb {width: 100%;border: 1px solid #ccc;}
-
.detail_tb .fied_header {height: 38px;line-height: 38px;border-left: none;border-bottom: 1px solid #ccc;background-color: #ececec;}
-
.detail_tb .fied_header th {text-align: center;border-right: 1px solid #ccc;color: #333;font-size: 14px;}
-
.detail_tb .fied_header th input {vertical-align: middle;}
-
.detail_tb tr {height: 38px;line-height: 38px;border-left: none;border-bottom: 1px solid #ccc;background-color: #fff;}
-
.detail_tb tr td {text-align: center;border-right: 1px solid #ccc;color: #666;font-size: 14px;}
-
.detail_tb tr td input {float: left;margin: 12px 5px 0 10px;}
-
.detail_tb tr td span {float: left;}
-
.detail_tb tr td select {display: inline-block;width: 90px;height: 24px;}
-
</style>
-
-
</head>
-
<body>
-
-
<table class="detail_tb" >
-
<thead>
-
<tr class="fied_header">
-
<th width="65"><input type="checkbox" value="number" id="number"> 序号</th>
-
<th width="110">孩子姓名</th>
-
<th width="130">家长电话</th>
-
<th width="110">介绍人孩子姓名</th>
-
<th width="130">介绍人电话</th>
-
<th width="150">报名时间</th>
-
<th width="100">分组情况</th>
-
<th width="100">拉新数量</th>
-
<th width="100">是否签到</th>
-
<th width="100">是否发奖</th>
-
</tr>
-
</thead>
-
<tbody id="tbody">
-
<tr>
-
<td width="65"><input type="checkbox" value="" id="" ><span>1</span></td>
-
<td width="110">张三</td>
-
<td width="130">13888888888</td>
-
<td width="110">李四</td>
-
<td width="130">13888888888</td>
-
<td width="150">2016/08/6 21:00</td>
-
<td width="100">
-
<select name="" id="">
-
<option value="">未分组</option>
-
<option value="">1</option>
-
<option value="">2</option>
-
</select>
-
</td>
-
<td width="100">33</td>
-
<td width="100">是</td>
-
<td width="100">
-
<select name="" id="">
-
<option value="">否</option>
-
<option value="">奖品1</option>
-
<option value="">奖品2</option>
-
</select>
-
</td>
-
</tr>
-
<tr>
-
<td width="65"><input type="checkbox" value="" id=""><span>2</span></td>
-
<td width="110">张四</td>
-
<td width="130">13888888888</td>
-
<td width="110">李四</td>
-
<td width="130">13888888888</td>
-
<td width="150">2016/08/6 21:00</td>
-
<td width="100">
-
<select name="" id="">
-
<option value="">未分组</option>
-
<option value="">1</option>
-
<option value="">2</option>
-
</select>
-
</td>
-
<td width="100">33</td>
-
<td width="100">是</td>
-
<td width="100">
-
<select name="" id="">
-
<option value="">否</option>
-
<option value="">奖品1</option>
-
<option value="">奖品2</option>
-
</select>
-
</td>
-
</tr>
-
<tbody>
-
</table>
-
-
-
<script src="https://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
-
<script type="text/javascript">
-
// 全选和反选
-
$("#number").click(function () {
-
var isChecked = $("#number").prop("checked");
-
$("#tbody input").prop("checked", isChecked);
-
})
-
-
// 单独选项控制全选
-
$("#tbody input").click(function () {
-
var allLength = $("#tbody input").length;
-
var checkedLength = $("#tbody input:checked").length;
-
if(allLength == checkedLength){
-
$("#number").prop("checked",true);
-
}else {
-
$("#number").prop("checked",false);
-
}
-
});
-
</script>
-
-
</body>
-
</html>
-
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
1.解决页面使用overflow: scroll在iOS上滑动卡顿的问题?
首先你可能会给页面的html和body增加了height: 100%, 然后就可能造成IOS上页面滑动的卡顿问题。解决方案是:
(1) 看是否能把body和html的height: 100%去除掉。
(2) 在滚动的容器中增加:-webkit-overflow-scrolling: touch或者给body增加:body {overflow-x: hidden}。
2.ios页面橡皮弹回效果遮挡页面选项卡?
(1) 有时body和html的height: 100%去除掉问题可能就没有了。
(2) 到达临界值的时候在阻止事件默认行为
var startY,endY; //记录手指触摸的起点坐标 $('body').on('touchstart',function (e) { startY = e.touches[0].pageY; }); $('body').on('touchmove',function (e) { endY = e.touches[0].pageY; //记录手指触摸的移动中的坐标 //手指下滑,页面到达顶端不能继续下滑 if(endY>startY&& $(window).scrollTop()<=0){ e.preventDefault(); } //手指上滑,页面到达底部能继续上滑 if(endY<startY&& $(window).scrollTop()+ $(window).height()>=$('body')[0].scrollHeight){ e.preventDefault(); } })
有时也会碰见弹窗出来后两个层的橡皮筋效果出现问题,我们可以在弹出弹出时给底层页面加上一个类名,类名禁止页面滑动这样下层的橡皮筋效果就会被禁止,就不会影响弹窗层。 3.IOS机型margin属性无效问题? (1) 设置html body的高度为百分比时,margin-bottom在safari里失效 (2) 直接padding代替margin 4.Ios绑定点击事件不执行? (1)添加样式cursor :pointer。点击后消除背景闪一下的css:-webkit-tap-highlight-color:transparent; 5.Ios键盘换行变为搜索? 首先,input 要放在 form里面。 这时 "换行" 已经变成 “前往”。 如果想变成 “搜索”,input 设置 type="search"。 6.Jq对a标签点击事件不生效? 出现这种情况的原因不明,有的朋友解释:我们平时都是点击的A标签中的文字了。 所以要想用JS模拟点击A标签事件,就得先往A标签中的文字添加能被JS捕获的元素,然后再用JS模拟点击该元素即可。但是我觉得不合理,虽然找不到原因但是解决办法还是有的。 (1)document.getElementById("abc ").click(); (2)$("#abc ")[0].click(); 7.有时因为服务器或者别的原因导致页面上的图片没有找到? 这是我们想需要用一个本地的图片代替没有找的的图片
<script type="text/javascript"> function nofind(){ var img=event.srcElement; img.src="images/logoError.png"; img.onerror=null; 控制不要一直跳动 } </script> <img src="images/logo.png" />8.transform属性影响position:fixed?
(1)规范中有规定:如果元素的transform值不为none,则该元素会生成包含块和层叠上下文。CSS Transforms Module Level 1不只在手机上,电脑上也一样。除了fixed元素会受影响之外,z-index(层叠上下文)值也会受影响。绝对定位元素等和包含块有关的属性都会受到影响。当然如果transform元素的display值为inline时又会有所不同。最简单的解决方法就是transform元素内部不能有absolute、fixed元素.
9.ios对position: fixed不太友好,有时我们需要加点处理?
在安卓上面,点击页面底部的输入框,软键盘弹出,页面移动上移。
而ios上面,点击页面底部输入框,软键盘弹出,输入框看不到了。。。查资料说什么的都有,iscroll,jquery-moblie,absolute,fixe,static都非常复杂,要改很多。。。
让他弹出时让滚动条在部
var u = navigator.userAgent, app = navigator.appVersion; var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端 if (isiOS) { $('textarea').focus(function () { window.setTimeout('scrollBottom()', 500); }); } function scrollBottom() { window.scrollTo(0, $('body').height()); }10.jq validate插件验证问题?
(1)所以的input必须有name不然会出错
11.有时手机会出现断网的情况,我没可能会对断网的情况做一些处理?
(1)navigator.onLine可判断是否是脱机状态.
12.判断对象的长度?
(1)用Object.keys,Object.keys方法返回的是一个数组,数组里面装的是对象的属性
var person = { "name" : "zhangshan", "sex" : "man", "age" : "50", "height" : "180", "phone" : "1xxxxxxxxxx", "email" : "xxxxxxxxx@xxx.com" }; var arr = Object.keys(person); console.log(arr.length);(2)Object.getOwnPropertyNames(obj).length
13.上一题我们用到了Object.keys与Object.getOwnPropertyNames他们的区别?
Object.keys定义:返回一个对象可枚举属性的字符串数组;
Object.getOwnPropertyNames定义:返回一个对象可枚举、不可枚举属性的名称;
属性的可枚举性、不可枚举性:定义:可枚举属性是指那些内部 “可枚举” 标志设置为 true 的属性,对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true,对于通过 Object.defineProperty 等定义的属性,该标识值默认为 false。
var obj = { "prop1": "v1" };
Object.defineProperty(obj, "prop2", { value: "v2", enumerable: false });
console.log(Object.keys(obj).length); //output:1 console.log(Object.getOwnPropertyNames(obj).length); //output:2 console.log(Object.keys(obj)); //output:Array[1] => [0: "prop1"] console.log(Object.getOwnPropertyNames(obj)); //output:Array[2] => [0: "prop1", 1: "prop2"]
综合实例
var obj = { "prop1": "v1" }; Object.defineProperty(obj, "prop2", { value: "v2", enumerable: false}); console.log(obj.hasOwnProperty("prop1")); //output: true console.log(obj.hasOwnProperty("prop2")); //output: true console.log(obj.propertyIsEnumerable("prop1")); //output: true console.log(obj.propertyIsEnumerable("prop2")); //output: false console.log('prop1' in obj); //output: true console.log('prop2' in obj); //output: true for (var item in obj) { console.log(item); } //output:prop1 for (var item in Object.getOwnPropertyNames(obj)) { console.log(Object.getOwnPropertyNames(obj)[item]); } //ouput:[prop1,prop2]
14.移动开发不同手机弹出数字键盘问题?
(1)type="tel"
iOS和Android的键盘表现都差不多
(2)type="number"
优点是Android下实现的一个真正的数字键盘
缺点一:iOS下不是九宫格键盘,输入不方便
缺点二:旧版Android(包括微信所用的X5内核)在输入框后面会有超级鸡肋的小尾巴,好在Android 4.4.4以后给去掉了。
不过对于缺点二,我们可以用webkit私有的伪元素给fix掉:
input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; appearance: none; margin: 0; }
(3)pattern属性
pattern用于验证表单输入的内容,通常HTML5的type属性,比如email、tel、number、data类、url等,已经自带了简单的数据格式验证功能了,加上pattern后,前端部分的验证更加简单了。
显而易见,pattern的属性值要用正则表达式。
实例 简单的数字验证
数字的验证有两个:
<input type="number" pattern="d">
<input type="number" pattern="[0-9]*">
15.input[number]类型输入非数字字符
js获取的值是空;比如-12,+123等
16.Javascript:history.go()和history.back()的用法与区别?
简单的说就是:go(-1):返回上一页,原页面表单中的内容会丢失;back():返回上一页,原页表表单中的内容会保留。history.go(-1):后退+刷新history.back():后退
之所以注意到这个区别,是因为不同的浏览器后退行为也是有区别的,而区别就跟javascript:history.go()和history.back()的区别类似。
Chrome和ff浏览器后退页面,会刷新后退的页面,若有数据请求也会提交数据申请。类似于history.go(-1);
而safari(包括桌面版和ipad版)的后退按钮则不会刷新页面,也不会提交数据申请。类似于javascript:history.back();
17.Meta基础知识:
<meta name="viewport"content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
// width 设置viewport宽度,为一个正整数,或字符串‘device-width’
// height 设置viewport高度,一般设置了宽度,会自动解析出高度,可以不用设置
// initial-scale 默认缩放比例,为一个数字,可以带小数
// minimum-scale 允许用户最小缩放比例,为一个数字,可以带小数
// maximum-scale 允许用户最大缩放比例,为一个数字,可以带小数
// user-scalable 是否允许手动缩放
空白页基本meta标签
<!-- 设置缩放 -->
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" />
<!-- 可隐藏地址栏,仅针对IOS的Safari(注:IOS7.0版本以后,safari上已看不到效果) -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- 仅针对IOS的Safari顶端状态条的样式(可选default/black/black-translucent ) -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<!-- IOS中禁用将数字识别为电话号码/忽略Android平台中对邮箱地址的识别 -->
<meta name="format-detection"content="telephone=no, email=no" />
其他meta标签
<!-- 启用360浏览器的极速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微软的老式浏览器 -->
<meta name="MobileOptimized" content="320">
<!-- uc强制竖屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 点击无高光 -->
<meta name="msapplication-tap-highlight" content="no">
18.移动端如何定义字体font-family?
@ --------------------------------------中文字体的英文名称
@ 宋体 SimSun
@ 黑体 SimHei
@ 微信雅黑 Microsoft Yahei
@ 微软正黑体 Microsoft JhengHei
@ 新宋体 NSimSun
@ 新细明体 MingLiU
@ 细明体 MingLiU
@ 标楷体 DFKai-SB
@ 仿宋 FangSong
@ 楷体 KaiTi
@ 仿宋_GB2312 FangSong_GB2312
@ 楷体_GB2312 KaiTi_GB2312
@
@ 说明:中文字体多数使用宋体、雅黑,英文用Helvetica
body { font-family: Microsoft Yahei,SimSun,Helvetica; }
19.打电话发短信写邮件怎么实现?
// 一、打电话 <a href="tel:0755-10086">打电话给:0755-10086</a> // 二、发短信,winphone系统无效 <a href="sms:10086">发短信给: 10086</a> // 三、写邮件 <a href="mailto:863139978@qq.com">点击我发邮件</a> //2.收件地址后添加?cc=开头,可添加抄送地址(Android存在兼容问题) <a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net">点击我发邮件</a> //3.跟着抄送地址后,写上&bcc=,可添加密件抄送地址(Android存在兼容问题) <a href="mailto:863139978@qq.com?cc=zhangqian0406@yeah.net&bcc=384900096@qq.com">点击我发邮件</a> //4.包含多个收件人、抄送、密件抄送人,用分号(;)隔开多个邮件人的地址 <a href="mailto:863139978@qq.com;[url=mailto:384900096@qq.com]384900096@qq.com[/url]">点击我发邮件</a> //5.包含主题,用?subject= <a href="mailto:863139978@qq.com?subject=邮件主题">点击我发邮件</a> //6.包含内容,用?body=;如内容包含文本,使用%0A给文本换行 <a href="mailto:863139978@qq.com?body=邮件主题内容%0A腾讯诚信%0A期待您的到来">点击我发邮件</a> //7.内容包含链接,含http(s)://等的文本自动转化为链接 <a href="mailto:863139978@qq.com?body=http://www.baidu.com">点击我发邮件</a> //8.内容包含图片(PC不支持) <a href="mailto:863139978@qq.com?body=<img src='images/1.jpg' />">点击我发邮件</a> //9.完整示例 <a href="mailto:863139978@qq.com;[url=mailto:384900096@qq.com]384900096@qq.com[/url]?cc=zhangqian0406@yeah.net&bcc=993233461@qq.com&subject=[邮件主题]&body=腾讯诚邀您参与%0A%0A[url=http://www.baidu.com]http://www.baidu.com[/url]%0A%0A<img src='images/1.jpg' />">点击我发邮件</a>
|
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
最近在对《React Native移动开发实战》一书进行部分修订和升级。在React Native开发中,免不了会涉及到原生代码与JS层的消息传递等问题,那么React Native究竟是如何实现与原生的互相操作的呢?
原生给JS传值,主要依靠属性,也就是通过initialProperties,这个RCTRootView的初始化函数的参数来完成。通过RCTRootView的初始化函数你可以将任意属性传递给React Native应用,参数initialProperties必须是NSDictionary的一个实例。RCTRootView有一个appProperties属性,修改这个属性,JS端会调用相应的渲染方法。
使用RCTRootView将React Natvie视图封装到原生组件中。RCTRootView是一个UIView容器,承载着React Native应用。同时它也提供了一个联通原生端和被托管端的接口。
例如有下面一段OC代码:
下面是JS层的处理:
不管OC中关于initialProperties的名字叫什么,在JS中都是this.props开头,然后接下来才是key名字。
RCTRootView同样提供了一个可读写的属性appProperties。在appProperties设置之后,React Native应用将会根据新的属性重新渲染。当然,只有在新属性和旧的属性有更改时更新才会被触发。
可以随时更新属性,但是更新必须在主线程中进行,读取则可以在任何线程中进行。
.h的文件代码:
.m的文件代码:
为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。如果你不指定,默认就会使用这个Objective-C类的名字。
并且必须明确的声明要给Javascript导出的方法,否则React Native不会导出任何方法。OC中声明要给Javascript导出的方法,通过RCT_EXPORT_METHOD()宏来实现。
要用到NativeModules则要引入相应的命名空间import { NativeModules } from ‘react-native’;然后再进行调用CalendarManager.doSomething(‘sdfsdf’,’sdfsdfs’);桥接到Javascript的方法返回值类型必须是void。React Native的桥接操作是异步的,所以要返回结果给Javascript,你必须通过回调或者触发事件来进行。
说明:第一个参数代表从JavaScript传过来的数据,第二个参数是回调方法;
RCT_EXPORT_METHOD 支持所有标准JSON类型,包括:
除此以外,任何RCTConvert类支持的的类型也都可以使用(参见RCTConvert了解更多信息)。RCTConvert还提供了一系列辅助函数,用来接收一个JSON值并转换到原生Objective-C类型或类。例如:
如果需要从iOS原生方法发送数据到JavaScript中,那么使用eventDispatcher。例如:
在JavaScript中可以这样订阅事件,通常需要在componentWillUnmount函数中取消事件的订阅。
用NativeAppEventEmitter.addListener中注册一个通知,之后再OC中通过bridge.eventDispatcher sendAppEventWithName发送一个通知,这样就形成了调用关系。
原生给React Native传参
原生给React Native传值
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; NSArray *imageList = @[@"http://foo.com/bar1.png",
@"http://foo.com/bar2.png"]; NSDictionary *wjyprops = @{@"images" : imageList};
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"ReactNativeProject" initialProperties:wjyprops
launchOptions:launchOptions];
import React, { Component } from 'react'; import {
AppRegistry,
View,
Image,
} from 'react-native'; class ImageBrowserApp extends Component { renderImage(imgURI) { return (
<Image source={{uri: imgURI}} />
);
}
render() { return (
<View>
{this.props.images.map(this.renderImage)}
</View>
);
}
}
AppRegistry.registerComponent('ImageBrowserApp', () => ImageBrowserApp);
{"rootTag":1,"initialProps":{"images":["http://foo.com/bar1.png","http://foo.com/bar2.png"]}}.
使用appProperties进行参数传递
NSArray *imageList = @[@"http://foo.com/bar3.png", @"http://foo.com/bar4.png"]; rootView.appProperties = @{@"images" : imageList};
React Native执行原生方法及回调
React Native执行原生方法
#import <Foundation/Foundation.h> #import <RCTBridgeModule.h> @interface wjyTestManager : NSObject<RCTBridgeModule> @end
#import "wjyTestManager.h" @implementation wjyTestManager RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(doSomething:(NSString *)aString withA:(NSString *)a)
{ NSLog(@"%@,%@",aString,a);
} @end
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Alert,
TouchableHighlight,
} from 'react-native';
import {
NativeModules,
NativeAppEventEmitter
} from 'react-native'; var CalendarManager = NativeModules.wjyTestManager; class ReactNativeProject extends Component { render() { return (
<TouchableHighlight onPress={()=>CalendarManager.doSomething('sdfsdf','sdfsdfs')}>
<Text style={styles.text}
>点击 </Text>
</TouchableHighlight>
);
}
} const styles = StyleSheet.create({
text: {
flex: 1,
marginTop: 55,
fontWeight: 'bold' },
});
AppRegistry.registerComponent('ReactNativeProject', () => ReactNativeProject);
传参并回调
RCT_EXPORT_METHOD(testCallbackEvent:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback)
{ NSLog(@"当前名字为:%@",dictionary); NSArray *events=@[@"callback ", @"test ", @" array"];
callback(@[[NSNull null],events]);
}
JS层代码:
import {
NativeModules,
NativeAppEventEmitter
} from 'react-native'; var CalendarManager = NativeModules.wjyTestManager; class ReactNativeProject extends Component { render() { return (
<TouchableHighlight onPress={()=>{CalendarManager.testCallbackEvent(
{'name':'good','description':'http://www.lcode.org'},
(error,events)=>{ if(error){
console.error(error);
}else{
this.setState({events:events});
}
})}}
>
<Text style={styles.text}
>点击 </Text>
</TouchableHighlight>
);
}
}
参数类型说明
#import "RCTConvert.h" #import "RCTBridge.h" #import "RCTEventDispatcher.h" // 对外提供调用方法,为了演示事件传入属性字段 RCT_EXPORT_METHOD(testDictionaryEvent:(NSString *)name details:(NSDictionary *) dictionary)
{ NSString *location = [RCTConvert NSString:dictionary[@"thing"]]; NSDate *time = [RCTConvert NSDate:dictionary[@"time"]]; NSString *description=[RCTConvert NSString:dictionary[@"description"]]; NSString *info = [NSString stringWithFormat:@"Test: %@\nFor: %@\nTestTime: %@\nDescription: %@",name,location,time,description]; NSLog(@"%@", info);
}
iOS原生访问React Native
#import "RCTBridge.h" #import "RCTEventDispatcher.h" @implementation CalendarManager @synthesize bridge = _bridge; // 进行设置发送事件通知给JavaScript端 - (void)calendarEventReminderReceived:(NSNotification *)notification
{ NSString *name = [notification userInfo][@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder" body:@{@"name": name}];
} @end
import { NativeAppEventEmitter } from 'react-native';
var subscription = NativeAppEventEmitter.addListener( 'EventReminder',
(reminder) => console.log(reminder.name)
); ... // 千万不要忘记忘记取消订阅, 通常在componentWillUnmount函数中实现。
subscription.remove();
素材类网站
Unsplash是一个分享免费高质量照片的网站,照片分辨率都挺大,而且都是真实的摄影师作品,图片多是风景和静物:https://unsplash.com/
插件类网站
jq22,分享jQuery插件和提供各种jQuery的详细使用方法,在线预览,jQuery插件下载及教程:http://www.jq22.com/
http://www.htmleaf.com/ 这个网站与上一个网站类似,也提供了大量的jQuery插件。
layui,这是一个强大的模块化前端框架:http://www.layui.com/
H-ui,端框架,一个轻量级前端框架,简单免费,兼容性好,服务中国网站:http://www.h-ui.net/index.shtml
字体类网站
有字库,一个免下载字体,直接在线引用字体的网站:http://www.youziku.com/onlinefont/index
PS字体库,包含了几乎所有类型的字体,下载好安装,PS中就可以使用了:http://www.psjia.com/pssc/fontxz/list_18_3.html
图标类网站
iconfont,这是阿里巴巴旗下的图标库网站,直接搜索关键词就可以找到大批的图标。下载图标的时候我们还可以选择颜色、大小、格式,根据自己的需要下载就好了:http://www.iconfont.cn/plus
easyicon,这也是一个非常有名的图标库,与上面那个不同的是,这里的图标不是单一颜色的,而是设计好的颜色。下载图标也很简单,直接点击对应图标上面的格式就可以下载:http://www.easyicon.net/iconsearch/ios/
奥森图标(Font Awesome),提供丰富的矢量字体图标—通过CSS可以任意控制所有图标的大小 ,颜色,阴影:http://www.thinkcmf.com/font/search.html
配色类网站
http://colorhunt.co,这个网站给我们提供了很多的配色方案,我们直接使用就OK了。
使用方法也很简单,鼠标移动到对应的颜色上,我们就可以看到颜色的十六进制码,复制这个颜色到工具里就可以使用了。
https://webgradients.com/, 180种渐变方案供你选择,还可以直接复制CSS样式应用到网页中。
adobe,这个是Adobe公司出的,他提供了多种配色方案。我们点击圆盘中间的点,就可以调整出我们想要的配色方案:https://color.adobe.com/zh/create/color-wheel
http://www.colorhunter.com/,这是一个提取现有图片配色方案的工具。我们上传一张图片,它就会帮我们把图片的配色提取出来供我们使用。
bootcss,这个网站是为WEB设计,开发中经常用到的安全色。网站内列出了颜色的十六进制码和RGB码,复制粘贴就可以了:http://www.bootcss.com/p/websafecolors/
sioe,这是一个在线RGB和十六进制颜色码转换工具。在对应的位置填入十六进制代码,点击转换,我们就可以获取到RGB颜色的代码了:http://www.sioe.cn/yingyong/yanse-rgb-16/
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
js中构造函数的几种继承模式浅析
一、原型链模式继承
利用原型让一个引用类型继承另一个引用类型的属性和方法 。
用的最多。
缺点:不可传参,不可多继承。
-
function People(name, age) {//添加公有属性
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}//创建一个名为People的类
-
People.prototype.eat = function() {//添加私有属性
-
console.log(this.name + '贼能吃');
-
}
-
function Cat(color) {//创建一个名为Cat的类
-
this.color = color;
-
}
-
Cat.prototype = new People('小叮当', 200);//实例化一个People类,并赋值给Cat类的原型链
-
var cat = new Cat('蓝白色')
-
console.log(cat.name)//'小叮当'
-
cat.eat();//'小叮当贼能吃'
二、混合模式继承
用call的方法只能继承私有属性,所以再加一遍一遍原型链模式继承,原型链模式继承又把私有属性和公有属性都继承了一遍。
-
function People(name, age) { //创建一个父级People类
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '贼能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age); //通过call的形式继承
-
//通过call(this),将People的指向改为Cat的实例
-
}
-
var cat = new Cat('蓝白色', '小叮当', 1);
-
console.log(cat.name);//'小叮当'
-
cat.eat();//报错,
-
//继承不了公有属性,所以cat.eat()会报错;
为了继承公有属性,用原型链模式在把公有属性和方法继承过来,
-
function People(name, age) { //创建一个父级People类
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '贼能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age); //通过call的形式继承
-
//通过call(this),将People的指向改为Cat的实例
-
}
-
Cat.prototype = new People()
-
var cat = new Cat('蓝白色', '小叮当', 200)
-
console.log(cat)
-
console.log(cat.name); //'小叮当',在原型链继承的时候,就近原则,cat.name 先找到'小叮当',就不往下找了
-
cat.eat(); //'小叮当贼能吃'
三、拷贝继承
优点:可以多继承,可传参;
缺点:浪费资源,不能判断父级;
-
function People(name, age) { //创建一个父级People类
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '贼能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
var people = new People(name, age) //实例化一个People类
-
for (let i in people) {
-
this[i] = people[i]; //将people中的可枚举属性和方法遍历并附给Cat类,公有属性和私有属性都是可枚举属性;
-
}
-
}
-
var cat = new Cat('蓝白色', '小叮当', 2);
-
console.log(cat.name); //小叮当
-
cat.eat(); //小叮当贼能吃
四、寄生组合方式继承
优点:私有属性和公有属性都单独继承,可以传参;
私有属性可以多继承,公有属性不可多继承;
-
function People(name, age) {
-
name = name || 'xiaolan';
-
age = age || 18;
-
this.name = name;
-
this.age = age;
-
}
-
People.prototype.eat = function() {
-
console.log(this.name + '贼能吃');
-
}
-
-
function Cat(color, name, age) {
-
this.color = color;
-
People.call(this, name, age) //用call的形式把私有属性继承过来
-
}
-
-
function Fn() {} //创建一个中间构造函数,用来接收People的公有属性,为了防止创建实例Cat实例是影响原来的people构造函数
-
Fn.prototype = People.prototype;
-
Cat.prototype = new Fn(); //将中间构造函数Fn继承people的公有属性传给Cat的原型链
-
Cat.prototype.constructor = Cat; //由于上一步重置了Cat原型链的constructor属性,所以要重新给赋回来;
-
var cat = new Cat('蓝白色', '小叮当', 3);
-
console.log(cat.name); //'小叮当'
-
cat.eat() //'小叮当贼能吃
注:若有不严谨与错误的地方,请多指教!
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
问题总结 https://github.com/vuejs-templates/webpack/issues/260
首先npm install --save babel-polyfill
然后在main.js
中的最前面引入babel-polyfill
import 'babel-polyfill'
在index.html 加入以下代码(非必须)
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
在config中的webpack.base.conf.js
中,修改编译配置
-
entry:{
-
app:['babel-polyfill','./src/main.js']
-
}
当然,如果你只用到了 axios
对 promise
进行兼容,可以只用 es6-promise
npm install es6-promise --save
在 main.js
中的最前面 引入
import 'es6-promise/auto'
那么,就有一个问题了,build之后的dist文件只有放在服务器上才能查看,但本地如何查看呢,参考一下配置
修改config文件夹中的index.js文件,将build对象中的打包路径,'/
‘改为'./'
,由绝对路径改为相对路径,建议将sourceMap
改为false
,编译的时候会快一点
build: { assetsPublicPath: './', productionSourceMap: false, },
修改完之后,重新 npm run build ,得到新的dist文件夹
然后进入dist文件夹
cd dist
全局安装简易node服务器
npm install http-server -g
启动简易node服务器
http-server
出现如下图所示,就代表你的服务器启动成功了,那你也能在5000端口查看编译打包后的项目了,可以在ie浏览器中直接测试了
IE在处理日期的时候,不支持-支持/的日期方式 如 2017-01-01应该
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise
所谓Promise ,简单说就是一个容器,里面保存着某个未来才回结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。
三种状态:
状态改变:
这两种情况只要发生,状态就凝固了,不会再变了,这时就称为resolved(已定型
基本用法
ES6规定,Promise对象是一个构造函数,用来生成Promise实例
Promise的源码分析:
曾几何时,我们的代码是这样的,为了拿到回调的结果,不得不
终于,我们的
首先我们要知道自己手写一个
我们先声明一个类,叫做
那么接下来我会分析上面代码的作用,原理
then方法是
这里主要做了将构造器中resolve和reject的结果传入
之前我们只是处理了同步情况下的Promise,简而言之所有操作都没有异步的成分在内。那么如果是异步该怎么办?
最早处理异步的方法就是callback,就相当于我让你帮我扫地,我会在给你发起任务时给你一个手机,之后我做自己的事情去,不用等你,等你扫完地就会打手机给我,诶,我就知道了地扫完了。这个手机就是callback,回调函数。
首先我们需要改一下构造器里的代码,分别添加两个回调函数的数组,分别对应成功回调和失败回调。他们的作用是当成功执行resolve或reject时,执行callback。
然后是then需要多加一个状态判断,当Promise中是异步操作时,需要在我们之前定义的回调函数数组中添加一个回调函数。
ok!大功告成,异步已经解决了
这也是
一下子多了很多方法,不用怕,我会一一解释
那就让我们来看看这个
它的作用是用来将onFufilled的返回值进行判断取值处理,把最后获得的值放入最外面那层的
我们现在已经基本完成了Promise的then方法,那么现在我们需要看看他的其他方法。
相信大家都知道catch这个方法是用来捕获Promise中的reject的值,也就是相当于then方法中的onRejected回调函数,那么问题就解决了。我们来看代码。
该方法是挂在Promise原型上的方法。当我们调用catch传callback的时候,就相当于是调用了then方法。
大家一定都看到过
这两个方法是直接可以通过class调用的,原理就是返回一个内部是resolve或reject的Promise对象。
all方法可以说是Promise中很常用的方法了,它的作用就是将一个数组的Promise对象放在其中,当全部resolve的时候就会执行then方法,当有一个reject的时候就会执行catch,并且他们的结果也是按着数组中的顺序来排放的,那么我们来实现一下。
其原理就是将参数中的数组取出遍历,每当执行成功都会执行
race方法虽然不常用,但是在Promise方法中也是一个能用得上的方法,它的作用是将一个
原理大家应该看懂了,很简单,就是遍历数组执行Promise,如果有一个
语法糖这三个字大家一定很熟悉,作为一个很Swag的前端工程师,对async/await这对兄弟肯定很熟悉,没错他们就是generator的语法糖。而我们这里要讲的语法糖是Promise的。
什么作用呢?看下面代码你就知道了
没错,我们可以方便的去调用他语法糖defer中的
Promise 的含义
Promise 对象的状态不受外界影响
Promise对象的状态改变,只有两种可能:
resolve
函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending
变为 resolved
),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject
函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending
变为 rejected
),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
1.回调地狱
callback hell
,这种环环相扣的代码可以说是相当恶心了
盖世英雄
出现了,他身披金甲圣衣、驾着七彩祥云。好吧打岔儿了,没错他就是我们的Promise
,那让我们来看看用了Promise
之后,上面的代码会变成什么样吧
2.重点开始,小眼睛都看过来
2.1 Promise/A+
Promise
,应该怎么去写,谁来告诉我们怎么写,需要遵循什么样的规则。当然这些你都不用担心,其实业界都是通过一个规则指标来生产Promise
的。让我们来看看是什么东西。传送门☞Promise/A+
2.2 constructor
Promise
,里面是构造函数。如果es6还有问题的可以去阮大大的博客上学习一下(传送门☞es6)
executor:
这是实例Promise
对象时在构造器中传入的参数,一般是一个function(resolve,reject){}
status:``Promise
的状态,一开始是默认的pendding状态,每当调用道resolve和reject方法时,就会改变其值,在后面的then方法中会用到
value:
resolve回调成功后,调用resolve方法里面的参数值
reason:
reject回调成功后,调用reject方法里面的参数值
resolve:
声明resolve方法在构造器内,通过传入的executor方法传入其中,用以给使用者回调
reject:
声明reject方法在构造器内,通过传入的executor方法传入其中,用以给使用者回调
2.3 then
Promise
中最为重要的方法,他的用法大家都应该已经知道,就是将Promise
中的resolve或者reject的结果拿到,那么我们就能知道这里的then方法需要两个参数,成功回调和失败回调,上代码!
onFufilled
和onRejected
中,注意这两个是使用者传入的参数,是个方法。所以你以为这么简单就完了?要想更Swag
的应对各种场景,我们必须得再完善。继续往下走!
3.异步的Promise
3.1 callback!!!!
3.2 resolvePromise
Promise
中的重头戏,我来介绍一下,我们在用Promise的时候可能会发现,当then函数中return了一个值,我们可以继续then下去,不过是什么值,都能在下一个then中获取,还有,当我们不在then中放入参数,例:promise.then().then()
,那么其后面的then依旧可以得到之前then返回的值,可能你现在想很迷惑。让我来解开你心中的忧愁,follow me。
Promise
?:首先我们要注意的一点是,then有返回值,then了之后还能在then,那就说明之前的then返回的必然是个Promise
。
setTimeout
?:因为Promise本身是一个异步方法,属于微任务一列,必须得在执行栈执行完了在去取他的值,所以所有的返回值都得包一层异步setTimeout。
resolvePromise
是什么?:这其实是官方Promise/A+的需求。因为你的then可以返回任何职,当然包括Promise
对象,而如果是Promise
对象,我们就需要将他拆解,直到它不是一个Promise
对象,取其中的值。
resolvePromise
到底长啥样。
Promise
的resolve函数中。
promise2
(then函数返回的Promise对象),x
(onFufilled函数的返回值),resolve、reject
(最外层的Promise上的resolve和reject)。
promise2
和x
?:首先在Promise/A+中写了需要判断这两者如果相等,需要抛出异常,我就来解释一下为什么,如果这两者相等,我们可以看下下面的例子,第一次p2是p1.then出来的结果是个Promise
对象,这个Promise
对象在被创建的时候调用了resolvePromise(promise2,x,resolve,reject)函数,又因为x等于其本身,是个Promise
,就需要then方法递归它,直到他不是Promise
对象,但是x(p2)的结果还在等待,他却想执行自己的then方法,就会导致等待。
resolvePromise
函数已经resolve或者reject了,那就不需要在执行下面的resolce或者reject。
resolvePromise
函数?:相信细心的人已经发现了,我这里使用了递归调用法,首先这是Promise/A+中要求的,其次是业务场景的需求,当我们碰到那种Promise的resolve里的Promise的resolve里又包了一个Promise的话,就需要递归取值,直到x不是Promise对象。
4.完善Promise
4.1 catch
4.2 resolve/reject
Promise.resolve()、Promise.reject()
这两种用法,它们的作用其实就是返回一个Promise对象,我们来实现一下。
4.3 all
processData
方法,processData
方法就是用来记录每个Promise的值和它对应的下标,当执行的次数等于数组长度时就会执行resolve,把arr的值给then。这里会有一个坑,如果你是通过arr数组的长度来判断他是否应该resolve的话就会出错,为什么呢?因为js数组的特性,导致如果先出来的是1位置上的值进arr,那么0位置上也会多一个空的值,所以不合理。
4.4 race
Promise
数组放入race中,哪个先执行完,race就直接执行完,并从then中取值。我们来实现一下吧。
Promise
执行成功就resolve。
Promise语法糖 deferred
Promise
对象。那么它还有没有另外的方法呢?答案是有的。我们需要在全局上安装promises-aplus-tests插件npm i promises-aplus-tests -g
,再输入promises-aplus-tests [js文件名] 即可验证你的Promise的规范。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计的小编 http://www.lanlanwork.com