如何区分Native App和Hybrid App

如何区分手机App是用Native实现还是用Webview实现

在开发Android App时,特别是强内容展现型的功能,会想在原生Native实现和web实现中做选择,做这种选择的时候,难免想看看竞品或其它App类似功能是用哪种方式实现的。但是如何判断其它App是用原生控件实现还是用Webview载入网页来实现呢?其实要想做到这一点不难,至少有两种办法:

一、抓包

这是比较原始,也是比较容易想到的,打开相应界面,抓取数据包看看,如果有url是返回比较完整的HTML代码,那基本就是Webview来实现的了。

二、利用系统开发人员工具

抓包的方法还是太麻烦,很多系统有更高级的开发人员工具功能,一般在设置里可以找到,有些手机可能需要特殊的操作才能打开开发人员工具功能。点击“设置”->“辅助功能”->“开发人员工具”,在绘图栏中找到“显示布局边界”并打开。这样所有应用的控件布局都一目了然了,Webview作为一个控件,只有一个边界框,所以通过这一点,就比较容易区分出一个界面是Webview实现的还是Native布局控件实现的,当然也不排除用一堆Webview来拼成一个界面的实现方法。

除了上面两种方法,一般来说,通过断开网络,刷新界面,观察内容缓存情况也可以对实现方式有个大致预判断,一般来说缓存做得好的,都是原生控制实现的,有界面局部缓存的就更大可能是原生的了。

前端开发经验总结-HTTP 常见状态码

前端开发经验总结系列之 HTTP 常见状态码

  • 1xx: 信息
  • 2xx: 成功
    • 200 OK 请求成功
    • 204 No Content 没有内容(没有response body,浏览器应该继续显示原来的文档)
    • 205 Reset Content 没有新文档(但浏览器应该重置它所显示的内容,用来强制浏览器清除表单输入内容)
  • 3xx: 重定向
    • 301 Moved Permanently 重定向(所请求的页面已经转移至新的url)
    • 302 Found 临时重定向(所请求的页面已经临时转移至新的url)
    • 304 Not Modified 文档未修改(客户的缓存资源是最新的, 要客户端使用缓存)
    • 307 Temporary Redirect 临时重定向(所请求的页面已经临时转移至新的url)
  • 4xx: 客户端错误
    • 400 Bad Request 坏请求(发送的Request中的数据有错误)
    • 403 Forbidden 请求被服务器拒绝了
    • 404 Not Found 未找到资源(服务器无法找到被请求的页面)
  • 5xx: 服务器错误
    • 500 Internal Server Error 内部服务器错误(服务器遇到一个错误,使其无法为请求提供服务)
    • 501 Internal Server Error 未实现(客户端发起的请求超出服务器的能力范围)

前端开发经验总结-网站性能优化

前端开发经验总结系列之网站性能优化

减少HTTP请求次数

合并图片、CSS、JS,改进首次访问用户等待时间。

把CSS放到顶部

把JS放到底部

避免使用CSS表达式

将CSS和JS放到外部文件中

目的是缓存,但有时候为了减少请求,也会直接写到页面里,需根据PV和IP的比例权衡。

精简CSS和JS

删除重复的JS和CSS

重复调用脚本,除了增加额外的HTTP请求外,多次运算也会浪费时间。在IE和Firefox中不管脚本是否可缓存,它们都存在重复运算JavaScript的问题。

可缓存的AJAX

“异步”并不意味着“即时”:Ajax并不能保证用户不会在等待异步的JavaScript和XML响应上花费时间。

使用GET来完成AJAX请求

当使用XMLHttpRequest时,浏览器中的POST方法是一个“两步走”的过程:首先发送文件头,然后才发送数据。因此使用GET获取数据时更加有意义。

减少DOM元素数量

是否存在一个是更贴切的标签可以使用?人生不仅仅是DIV+CSS

简历之道-如何写好技术简历

写好技术简历,应该遵循哪些原则

前言

有太多程序员可能因为不知道如何表达自己,而埋没了自己的才华,拿着原本可以拿到的一半的薪资,在一家默默无闻的公司里加班到深夜。

明明手握着最新技术的程序员们,不应该在写简历这件事上留下遗憾。我在写简历的过程中寻找和总结了一些经验,和大家分享一下:

版式

  • 使用对齐
  • 不必使用居中
  • 谨慎使用粗体
  • 避免不必要的折行
  • 使用制表符辅助对齐

个人信息

  • 不要使用不必要的条目名称
  • 使用分隔符增强电话号码的可读性
  • 使用可以点击的链接
  • 不要使用照片
  • 不要写无关个人信息
  • 使用客观事实而非主观描述
  • 考虑提供他人的评价
  • 不必写求职目标

技术能力

  • 不要堆砌技术名词
  • 对技术进行分类
  • 使用正确的技术名称
  • 不要写电脑能力
  • 按照熟悉程度对技术能力进行排序
  • 不要写过于特定的技术
  • 谨慎使用精通
  • 使用项目经验印证技术能力

项目经历

  • 按照时间对项目经历排序
  • 不要列出过多的项目
  • 强调成果而非过程
  • 使用量化结果而非抽象描述
  • 强调影响力和复杂度

教育背景

  • 不要写大学之前的教育经历
  • 不要写课程列表
  • 考虑使用成绩或排名
  • 考虑使用导师(老师)的评语
  • 考虑使用学业相关的奖项

个人爱好

  • 避免写个人爱好

英文简历

  • 不要出现拼写错误
  • 不要使用全角字符
  • 使用正确的词汇
  • 使用简洁的句子
  • 避免中式英语
  • 使用一致的时态
  • 考虑提供缩写词的解释
  • 使用Bullets组织长段
  • 打下良好的英文基础

其它

  • 考虑使用超链接
  • 考虑提供一个“加强版”简历
  • 考虑提供开发社区账号
  • 持续更新简历
  • 不断提升个人能力
  • 考虑征求他人意见

简历编写工具推荐用 MarkDown,这才是技术简历!

推荐文章如何写好技术简历 —— 实例、模板及工具

前端开发经验总结-JavaScript 对象继承形式

JavaScript 对象继承形式

1. 对象冒充继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function A(name) {
this.name = name;
this.sayHello = function() {
alert(this.name + 'say Hello!');
};
}

function B(name, id) {
this.temp = A;
this.temp(name); // 相当于 new A();
delete this.temp; // 防止在以后通过 temp 引用覆盖超类 A 的属性和方法
this.id = id;
this.checkId = function(ID) {
alert(this.id === ID);
};
}

用 call 实现的对象冒充继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Rect(width, height) {
this.width = width;
this.height = height;
this.area = function() {
return this.width * this.height;
};
}

function MyRect(width, height, name) {
Rect.call(this, width, height);
this.name = name;
this.show = function() {
alert(this.name + 'with area: ' + this.area());
}
}

2. 原型继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Person() {
this.name = 'Mike';
this.sayGoodbye = function() {
alert('GoodBye!');
};
}

Person.prototype.sayHello = function() {
alert('Hello!');
};

function Student() {}
Student.prototype = new Person();
Student.prototype.constructor = Student;

3. 综合方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var F = function() {};

function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
alert(this.name + 'say Hello!');
};

function Student(name, id) {
Person.call(this, name);
this.id = id;
}

F.prototype = Persion.prototype;
Student.prototype = new F();
Student.prototype.constructor = Student;
Student.uber = Persion.prototype; // 在子对象上打开一条通道,可以直接调用父对象的方法

Student.prototype.show = function() {
alert('Name is: ' + this.name + 'and Id is: ' + this.id);
}

前端开发经验总结-写样式的最佳实践

前端开发经验总结系列之写样式的最佳实践

  1. 坚持渐进增强策略,大胆使用新的 CSS3 技术,对低级浏览器保持基本的视觉支持。
  2. 设计 Html 结构是开发样式模块的核心工作,不要为了视觉效果迁就 HTML 结构。
  3. 使用 “fn-clear” 来清除浮动,慎用 “overflow: hidden;”。
  4. 样式模块不要依赖 reset.css ,要有对自身的 reset 代码。
  5. 不要去掉虚线框,为可用性考虑。
  6. 放弃 IE6 下的透明 png 修补方案。
  7. 使用 iconfont 代替雪碧图。
  8. 待续…

页面动态加入并执行 JavaScript 代码

页面动态加入 script 标签并执行其代码

在页面中动态追加HTML片段的时候,有时候动态添加的代码会含有script标签,比如用了一些模板引擎,或者你的代码有些复杂的时候。然而我们用DOM提供的innerHTML方式来添加代码的时候,script标签中的代码并不能执行,如果有src属性,指向的外联文件也不会被加载,这并不是浏览器的bug,因为W3C文档就是这么规定的。

那我们有什么办法可以恢复追加的script标签的代码执行能力呢?

重新构造script标签

这个思路其实非常简单,用innerHTML添加的script无法执行,但是我们script创建节点,并用appendChild追加上去是可以的,所以我们只需要做一下二次工作就可以了,看下面的例子:

页面上有个容器:

1
<div id="cnt"></div>

JS代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var html = '<div>html</div><script>alert(1);<\/script>';
var cnt = document.getElementById('cnt');
cnt.innerHTML = html;

var oldScript = cnt.getElementsByTagName('script')[0];
if (oldScript) {
// cnt.removeChild(oldScript);
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
// newScript.innerHTML = oldScript.innerHTML;
// newScript.text = oldScript.text;
newScript.src = oldScript.src;
// cnt.appendChild(newScript);
elem.replaceChild(script, oldScript);
}

这只是内联script的方法,如果是引用的外部js文件,那么我们需要为新创建的script节点指定src属性。

eval大法

虽然eval因为其安全性不推荐使用,但是在此特殊场景,使用eval确是非常简单的解决方案,就是把script标签中的代码eval一下手动执行,就ok了,看下面代码:

1
2
3
4
5
6
7
8
9
10
var html = '<div>html</div><script>alert(1);<\/script>';
var cnt = document.getElementById('cnt');
cnt.innerHTML = html;

var oldScript = cnt.getElementsByTagName('script')[0];
if (oldScript) {
cnt.removeChild(oldScript);
var scriptText = oldScript.text;
eval(scriptText);
}

对于内联的代码,简单而有效,如果是外部js文件,那么还是使用上面的方法,为新创建的script节点指定src属性。

document.write大法

此方法可以在页面上直接输出任何html内容,包含script标签的话会立即执行,所以也是一种方案,如下:

1
2
var html = '<div>html</div><script>alert(1);<\/script>';
document.write(html);

代码就直接执行了。但是他的缺点是如果代码写在文档底部,输出的内容会把页面上的其他内容全部覆盖,相当于清空了页面。解决的办法只有这样了:

1
<div id="cont"><script type="text/javascript">document.write(html);</script></div>

直接把它放在标签中,就会往这个标签中输出东西了。

使用jQuery

上面的方法说来说去,都不如jQuery简单,因为jQuery的html(),append()等方法内部已经做了处理,如果参数中含有script标签,内部会使用eval和创建新节点的方式进行处理,如果是外联的js文件,jQuery会发一个同步的ajax请求来获取代码,注意,是同步的!所以不论是内联的js代码还是外联的js文件,都可以正常执行,同时在执行完后删去script标签。所以,使用jQuery你只需要这样:

1
2
3
var html = '<div>html</div><script>alert(1);<\/script>';
// $('#cnt').append(html);
$('#cnt').html(html);

这个alert就妥妥的执行了。

本文参考自吕大豹(Double.Lv),感谢作者的无私分享!