暖色调

Every little helps


  • 首页

  • 归档

  • 分类

  • 标签

  • 关于

  • 搜索
close

javascript数据结构4-队列

发表于 2018-10-10   |   分类于 数据结构   |  

队列是一种先进先出(FIFO,first-in-first-out)的数据结构

javascript代码实现队列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<!doctype html>
<html>
<head>
<meta charset=utf-8 />
<title>Queue Sample</title>
</head>
<body>

<script type="text/javascript">
/*定义队列*/
function Queue(){
this.dataStore=[];
this.enqueue=enqueue;
this.dequeue=dequeue;
this.front=front;
this.back=back;
this.toStr=toStr;
this.isEmpty=isEmpty;
}

function enqueue(element){
this.dataStore.push(element);
}

function dequeue(){
return this.dataStore.shift();
}

function front(){
return this.dataStore[0];
}

function back(){
return this.dataStore[this.dataStore.length-1];
}

function toStr(){
var retStr="";
for(var i=0;i<this.dataStore.length;i++){
retStr+=this.dataStore[i]+"\n";
}
//console.log(retStr);
return retStr;
}
//判断是否为空
function isEmpty(){
if(this.dataStore.length==0){
return true;
}else{
return false;
}
}
var que=new Queue();
que.enqueue("Tom");
que.enqueue("Sam");
que.enqueue("Pom");
console.log(que.dataStore.length);
document.write(que.toStr());
que.dequeue();
document.write(que.toStr());
console.log(que.toStr);

</script>
</body>
</html>

举个案例:
常用队列模拟排队的人。下面我们使用队列来模拟跳方块舞的人。
当男男女女来到舞池,他们按照自己的性别排成两队。当舞池中有地方空出来时,选两个队列中的第一个人组成舞伴。他们身后的人各自向前移动一位,变成新的队首。当一对舞伴迈入舞池时,主持人会大声喊出他们的名字。当一对舞伴走出舞池,且两排队伍中有任意一队没人时,主持人也会把这个情况告诉大家。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
<!doctype html>
<html>
<head>
<meta charset=utf-8 />
<title>Queue Sample</title>
</head>
<body>

<script type="text/javascript">
/*定义队列*/
function Queue(){
this.dataStore=[];
this.enqueue=enqueue;
this.dequeue=dequeue;
this.front=front;
this.back=back;
this.toStr=toStr;
this.isEmpty=isEmpty;
}

function enqueue(element){
this.dataStore.push(element);
}

function dequeue(){
return this.dataStore.shift();
}

function front(){
return this.dataStore[0];
}

function back(){
return this.dataStore[this.dataStore.length-1];
}

function toStr(){
var retStr="";
for(var i=0;i<this.dataStore.length;i++){
retStr+=this.dataStore[i]+"\n";
}
//console.log(retStr);
return retStr;
}
//判断是否为空
function isEmpty(){
if(this.dataStore.length==0){
return true;
}else{
return false;
}
}

//舞蹈员性别 姓名
var allStr="F Shun F Tim M Huipin M Lanlan F Ping F Li F Lou M Funr F Sun M Pop";

function Dancer(name,sex){
this.name=name;
this.sex=sex;
}

//男女分队
function getDancers(males,females){
var numbers=allStr.split(" ");
//document.write(numbers);
//console.log(numbers);
for(var i=0;i<numbers.length-1;++i){
//var dances=numbers[i].trim();
var sex=numbers[i];
i++;
var name=numbers[i];
//console.log(name);
//console.log(sex);
if(sex == "F"){ //??????
famaleDances.enqueue(new Dancer(name,sex));
console.log(famaleDances);
}else{
maleDances.enqueue(new Dancer(name,sex));//整体对象存在队列中
}
}
}
//队首男女就是要出队的
function dance(males,famales){
document.write("The dance parter are: ");
document.write("<br />");
while(!males.isEmpty() && !famales.isEmpty()){
fperson=famales.dequeue();
// console.log(fperson);
document.write("The Famale dance is:"+fperson.name);
person=males.dequeue();
document.write(" and The Male dance is:"+person.name);
document.write("<br />");
}
}
var maleDances=new Queue();
var famaleDances=new Queue();
// document.write("1");
getDancers(maleDances,famaleDances);
dance(maleDances,famaleDances);

if(!famaleDances.isEmpty()){
document.write(famaleDances.front().name+"is waiting");
}

if(!maleDances.isEmpty()){
document.write(maleDances.front().name+"is waiting");
}
</script>
</body>
</html>

javascript数据结构3-栈

发表于 2018-10-10   |   分类于 数据结构   |  

后进先出(LIFO,last-in-first-out)的数据结构
类比:堆叠盘子,只能从上面拿走盘子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>栈</title>
</head>
<body>
<script type="text/javascript">
function Stack() {
this.dataStore = [];
this.pos = 0;
this.push=push;
this.pop=pop;
this.peek=peek;
this.clear = clear;
this.length=length;
}

function push(element){
this.dataStore[this.pos++]=element;
}
function peek(){
return this.dataStore[this.top-1];
}
function pop(){
return this.dataStore[--this.top];
}
function clear(){
this.top=0;
}
function length(){
return this.top;
}
/************************************************************************/
var s=new Stack();
s.push("Tom");
s.push("Som");
s.push("Dom");
s.push("Fom");
// document.write(s.dataStore);
console.log(s);
</script>
</body>
</html>

例子:
十进制转化为二进制,使用栈实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*数制间的相互转换*/
function mulBase(num,base){
var s=new Stack();
do{
s.push(num% base);
num=Math.floor(num /=base);
}while(num > 0);
var cov="";
console.log(s.length());
while(s.length() >0){
cov += s.pop();

}
return cov;
}
var num=32;
var newNum=mulBase(32,2); //十进制转换为二进制
console.log(newNum);
document.write(newNum);

javascript数据结构2-列表

发表于 2018-10-10   |   分类于 数据结构   |  

1. 类型定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
listSize(属性)         列表的元素个数
pos( 属性) 列表的当前位置
length( 属性) 返回列表中元素的个数
clear( 方法) 清空列表中的所有元素
toString( 方法) 返回列表的字符串形式
getElement( 方法) 返回当前位置的元素
insert( 方法) 在现有元素后插入新元素
append( 方法) 在列表的末尾添加新元素
remove( 方法) 从列表中删除元素
front( 方法) 将列表的当前位置设移动到第一个元素
end( 方法) 将列表的当前位置移动到最后一个元素
prev(方法) 将当前位置后移一位
next( 方法) 将当前位置前移一位
currPos( 方法) 返回列表的当前位置
moveTo(方法) 将当前位置移动到指定位置

2.实现列表类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>实现列表类</title>
</head>
<body>

<script type="text/javascript">
function List() {
this.listSize = 0;
this.pos = 0;
this.dataStore = [];
//this.clear = clear;
this.find = find;
this.toString = toString;
//this.insert = insert;
this.append = append;
this.remove = remove;
this.front = front;
//this.end = end;
// this.prev = prev;
//this.next = next;
this.length = length;
//this.currPos = currPos;
//this.moveTo = moveTo;
this.getElement = getElement;
// this.length = length;
}

function append(element) {
this.dataStore[this.listSize++] = element;
}

function find(element) {
for (var i = 0; i < this.dataStore.length; ++i) {
if (this.dataStore[i] == element) {
return i;
}
}
return -1;
}

function remove(element) {
var foundAt = this.find(element);
if (foundAt > -1) {
this.dataStore.splice(foundAt,1);
--this.listSize;
return true;
}
return false;
}

function toString() {
return this.dataStore;
}

function front(){
// return this.dataStore[0];
//或者
this.pos=0;
}
function getElement(){
return this.dataStore[this.pos];
}
var names = new List();
names.append("Cynthia");
names.append("Raymond");
names.append("Barbara");
console.log(names.toString());
names.remove("Raymond");
console.log(names.toString());
// console.log(names.front());
names.front();
console.log(names.getElement());
</script>
</body>
</html>

3.实际例子

从txt文件中读取数据(注意:这种方法只是适合在IE浏览器)
文档内容:

1.sam
2.tim
3.jom
4.dim
5.pop
6.hello
7.ming

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题</title>
</head>
<body>
<script type="text/javascript">
function List(){
this.listSize = 0;
this.pos = 0;
this.dataStore = [];
//this.clear = clear;
this.find = find;
this.toString = toString;
//this.insert = insert;
this.append = append;
this.remove = remove;
this.front = front;
this.end = end;
//this.prev = prev;
this.next = next;
this.length = length;
this.currPos = currPos;
//this.moveTo = moveTo;
this.getElement = getElement;
this.length = length;
}

function append(element){
this.dataStore[this.listSize++]=element;
}
function find(element){
for (var i = 0; i < this.dataStore.length; i++) {
if(this.dataStore[i]==element){
return i;
}
};
return -1;
}

function remove(element){
var foundAt=this.find(element);
if(foundAt > -1){
this.dataStore.splice(foundAt,1);
--this.listSize;
return true;
}
return false;
}

function toString(){
return this.dataStore;
}

function front(){
// return this.dataStore[0];
this.pos=0;
}
function end(){
// return this.dataStore[0];
this.pos=this.listSize-1;
}
function currPos(){
return this.pos;
}
function next(){
if(this.pos<this.listSize-1){
++this.pos();
}
}
function getElement(){
return this.dataStore[this.pos];
}
function createArr(){
// var arr=read(file).split("/n");
//读取文件
var s=[],arr=[];
var fso, f1, ts;
var ForReading = 1;
var src="E:\\jsDS\\test.txt";
fso = new ActiveXObject("Scripting.FileSystemObject");
ts = fso.OpenTextFile(src,1,true);
// document.all.mailbdy.value=ts.ReadAll();
while (!ts.AtEndOfStream)
{
str=ts.Readline();
// s=str.split("\n");
s.push(str);
}
/*console.log("==================");
console.log(s);
console.log("==================");*/
for (var i = 0; i < s.length; i++) {
arr[i]=s[i].trim();
};
return arr;
}

function displayList(list){
// for (list.front();list.currPos()<list.length();list.next()) {
var lists=[];
list.front();
while(list.currPos() < list.length){
lists.push(list.getElement());
list.next();
}
return lists;

}

var movies=createArr();
var mlist=new List();
for (var i = 0; i < movies.length; i++) {
console.log(movies[i]);
mlist.append(movies[i]);
};
console.log(mlist);
//console.log(displayList(mlist));
</script>
</body>
</html>

javascript数据结构1-数组

发表于 2018-10-10   |   分类于 数据结构   |  

书籍:

数据结构与算法javascript描述

数组比较简单,这里只是简单介绍:

1.使用数组

1.1 创建数组

1
2
3
4
//第一种形式
var numbers = new Array(3);
//第二种形式
var numbers = [7,4,1776];

大多数JavaScript 专家推荐使用[]操作符,和使用Array 的构造函数相比,这种方式被认为效率更高(new创建的对象,会一直存在于内存中)

1.2 读写数组

1
2
3
4
5
var numbers = [1,2,3,5,8,13,21];
var sum = 0;
for (var i = 0; i < numbers.length; ++i) {
sum += numbers[i];
}

1.3 字符串生成数组

1
2
3
4
5
6
//下面的这一小段程序演示了split() 方法的工作原理:
var sentence = "the quick brown fox jumped over the lazy dog";
var words = sentence.split(" ");
for (var i = 0; i < words.length; ++i) {
console.log("word " + i + ": " + words[i]);
}

1.4 对数组的整体性操作

1
2
3
4
5
6
7
var nums = [];
for (var i = 0; i < 100; ++i) {
nums[i] = i+1;
}
var samenums = nums;
nums[0] = 400;
console.log(samenums[0]); // 显示400

这种行为被称为浅复制,新数组依然指向原来的数组。一个更好的方案是使用深复制,将
原数组中的每一个元素都复制一份到新数组中。可以写一个深复制函数来做这件事:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function copy(arr1, arr2) {
for (var i = 0; i < arr1.length; ++i) {
arr2[i] = arr1[i];
}
}
//这样,下述代码片段的输出就和我们希望的一样了:
var nums = [];
for (var i = 0; i < 100; ++i) {
nums[i] = i+1;
}
var samenums = [];
copy(nums, samenums);
nums[0] = 400;
console.log(samenums[0]); // 显示 1

2. 存取函数

2.1 查找元素

1
2
3
4
5
6
7
8
9
10
var names = ["David", "Cynthia", "Raymond", "Clayton", "Jennifer"];
putstr("Enter a name to search for: ");
var name = readline();
var position = names.indexOf(name);
if (position >= 0) {
console.log("Found " + name + " at position " + position);
}
else {
console.log(name + " not found in array.");
}

2.2 两个函数使用

concat 连接
splice 截取
join() 和toString() 将数组转化为字符串

1
2
3
4
5
6
7
8
9
var cisDept = ["Mike", "Clayton", "Terrill", "Danny", "Jennifer"];
var dmpDept = ["Raymond", "Cynthia", "Bryan"];
var itDiv = cis.concat(dmp);
console.log(itDiv);
itDiv = dmp.concat(cisDept);
console.log(itDiv);
//输出为:
Mike,Clayton,Terrill,Danny,Jennifer,Raymond,Cynthia,Bryan
Raymond,Cynthia,Bryan,Mike,Clayton,Terrill,Danny,Jennifer

3. 可变函数

简单函数:

1
2
3
4
push()          末尾增加元素
unshift() 在开头添加元素
pop() 在末尾删除元素
shift() 在开头删除元素

从数组中间删除元素:

1
2
3
4
var nums = [1,2,3,7,8,9];
var newElements = [4,5,6];
nums.splice(3,0,newElements);
console.log(nums); // 1,2,3,4,5,6,7,8,9

排序函数:

1
2
3
var nums = [1,2,3,4,5];
nums.reverse();
console.log(nums); // 5,4,3,2,1
1
2
3
var names = ["David","Mike","Cynthia","Clayton","Bryan","Raymond"];
names.sort();
console.log(names); // Bryan,Clayton,Cynthia,David,Mike,Raymond

自定义:

1
2
3
4
5
6
7
function compare(num1, num2) {
return num1 - num2;
}
var nums = [3,1,2,100,4,200];
nums.sort(compare);
console.log(nums); // 1,2,3,4,100,200
//sort() 函数使用了compare() 函数对数组按照数字大小进行排序,而不是按照字典顺序。

4.迭代器

1
2
3
4
5
6
7
   函数      说明                           是否生成新数组
foreach() 全部遍历 否
every() 全部返回true,才返回true 否
some() 只要一个返回true,就返回true 否
reduce() 不断调用累加值 否
map() 符合条件的,类比foreach() 是
filter() 返回结果为true的函数 是

5.二维数组和多维数组

1
2
3
4
5
6
7
8
9
10
Array.matrix = function(numrows, numcols, initial) {
var arr = [];
for (var i = 0; i < numrows; ++i) {
var columns = [];
for (var j = 0; j < numcols; ++j) {
columns[j] = initial;
}
arr[i] = columns;
}
return

6.两种特殊的数组

数组的函数同样适用

对象数组

1
2
3
4
function Point(x,y) {
this.x = x;
this.y = y;
}

对象中的数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function weekTemps() {
this.dataStore = [];
this.add = add;
this.average = average;
}
function add(temp) {
this.dataStore.push(temp);
}
function average() {
var total = 0;
for (var i = 0; i < this.dataStore.length; ++i) {
total += this.dataStore[i];
}
return total / this.dataStore.length;
}
var thisWeek = new weekTemps();
thisWeek.add(52);
thisWeek.add(55);
thisWeek.add(61);
thisWeek.add(65);
thisWeek.add(55);
thisWeek.add(50);
thisWeek.add(52);
thisWeek.add(49);
console.log(thisWeek.average()); // 显示54.875

HTTP/2 的优势

发表于 2018-10-10   |   分类于 HTTP   |  

相比 HTTP/1.x,HTTP/2 在底层传输做了很大的改动和优化:

  1. HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式。二进制格式在协议的解析和优化扩展上带来更多的优势和可能。
  2. HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络的流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。头压缩能够很好的解决该问题。
  3. 多路复用,直白的说就是所有的请求都是通过一个 TCP 连接并发完成。HTTP/1.x 虽然能利用一个连接完成多次请求,但是多个请求之间是有先后顺序的,后面发送的请求必须等待上一个请求返回才能发送响应。这会很容易导致后面的请求被阻塞,而 HTTP/2 做到了真正的并发请求。同时, 流还支持优先级和流量控制。
  4. Server Push:服务端能够更快的把资源推送给客户端。例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 再发送这些请求。当客户端需要的时候,它已经在客户端了。

ccgis移动版

发表于 2018-10-10   |   分类于 项目总结   |  

1.系统设计

简介

对地图工作空间的管理及展示、发表评论、点赞,能够集成第三方地图、定位、拍照及上传照片、记录路线轨迹,提供了用户信息管理功能,实现了全国空气质量图表展示专题模块。
网址:https://ccgis.cn/mapb/mobile/home/

功能设计

系统分为以下五个功能模块,分别是首页、地图数据管理、地图模块、属性数据管理、用户信息管理,如图所示。

代码文件组织

在mobile文件夹下包含以下文件夹:common(存放公共的类库、图片等)、home(首页)、mapmgr(地图数据管理模块)、mapmodule(地图模块)、tablemgr(属性数据管理模块)、usermgr(用户信息管理模块)。
每个模块文件夹下包含:common(模块需要的公共资源)、modules(该模块下的子模块)、index.html(网页文档)。

2.关键技术

2.1 适配不同分辨率的设备

为了适配不同型号的移动终端,需使用viewport动态设置页面宽度。使用方法如下:在网页的head页面元素中加入meta标签。

1
2
<meta name="viewport" content="width=device-width,initial-scale=1.0,
maximum-scale=1.0, user-scalable=0">

该标签的作用是让当前viewport的宽度等于设备的宽度,页面第一次加载时的缩放比例为1,同时不允许用户手动缩放。

2.2 空气质量图表展示

利用百度API提供的BMap.LocalCity获取用户当前所在城市,通过逻辑判断获取数据库最新的当前城市的空气质量数据。仪表盘是用来表示当前城市空气质量指数平均值及所属污染级别。利用series将仪表盘的区间范围设置为[0,500],以10段进行分割,用绿色(#32f43e)、黄色(#e4f33e)、橙色(#e4993c)、红色(#f60003)、紫色(#9f034c)、褐红色(#800025)6种颜色将10段划为空气质量级别对应的优、良、轻度污染、中度污染、重度污染和严重污染。

热力图是基于Canvas的,因此在使用热力图之前需要利用isSupportCanvas判断浏览器是否支持Canvas,然后需要生成一个百度地图实例map,在已经生成的地图上将热力图叠加上去即可,其中传入的参数points为用户选择的空气质量指标对应的包含站点经纬度及指标值的对象数组。

2.3 用户评论、点赞

1、用户评论实现思路:在g_usercomment表中插入一条记录;判断评论总数表中是否有该地图的记录,有就更新g_usercommentNum表中该条记录,否则插入一条新的记录。

2、用户点赞实现思路:查询g_userpraise表中是否有该用户为该地图点赞的记录,有的话则删除该记录,并更新g_userpraiseNum表中对应记录点赞数减1;若没有记录,则在g_userpraise表添加一条记录,并判断g_userpraiseNum(点赞总数表)中是否有该地图的记录,有就更新g_userpraiseNum表中该条记录,否则插入一条新的记录。

2.4 定位、逆地理编码

2.4.1 地图定位

1、利用HTML5 geolocation服务的getCurrentPosition方法获取经纬度,使用之前检测浏览器是否支持HTML5 geolocation。
2、获取位置成功后,若为上海地图则转为上海坐标,实例化一个标注加到地图上并zoomTo到该位置;若不是则直接添加标注和zoomTo到该位置。

2.4.2 逆地理编码

1、将之前获取的经纬度坐标转为百度地图上的经纬度,接口由zdoz提供。
2、利用百度地图API反地理编码得到该经纬度对应的地址信息:

1
var myGeo = new BMap.Geocoder();

2.5 拍照

在移动端实现拍照或选取相册使用的是类型为file的input标签,但是不需要使用其默认的样式,因此将input标签css样式的透明度opacity设置为0,并在其上覆盖其他元素。
触发了file类型的input元素的onchange事件后,通过File API提供的异步读取文件的接口FileReader,使用readAsDataURL方法读取文件内容。
在上传图片之前,为了实现图片的预览,使用createObjectURL方法(也可使用FileReader对象的readAsDataURL方法),该方法可创建一个新的对象URL,通过这个URL可以获取到传入的file对象或blob对象的完整内容,然后将图片元素的src属性指向这个URL,实现图片预览功能:

1
2
3
var URL = window.URL || window.webkitURL;
var blob = URL.createObjectURL(files[0]);
$("#firstImg").attr("src",blob);

使用geoserver服务器fileserver接口的putbase64方法,将文件上传到服务器中,并在数据库中记录相关信息,包括:用户ID、经纬度、描述信息、图片存放的路径和时间。

2.6 记录路线轨迹

开启记录轨迹模式后,每隔3秒记录下当前用户所在位置,可暂定记录,也可继续开启该模式,还可以将记录的轨迹上传到服务器供下次查看。

首先需要判断浏览器是否支持HTML5的geolocation,若不支持或获取位置失败则根据错误类型给出相应的提示。利用 navigator.geolocation对象的getCurrentPosition方法获取用户位置,并利用setInterval每隔3秒获取一次(可改为直接使用watchPosition方法,而不需要使用间隔调用)。

获取到用户位置信息后记录下经纬度数据,若是第一次获取实例化一个标注点添加到地图上,并将地图缩放到该点的位置;之后每次调用判断当前记录的位置信息和上一次记录的经纬度是否相同,如果不同就记录下该点位置,并绘制路线:根据所记录的位置实例化一个线要素,并根据第一个和最后一个点的位置信息实例化起点和终点的标注点。判断最后一个点是否在屏幕中间区域,即(x坐标是否位于地图宽度的1/4到3/4处,y坐标是否位于地图高度的1/4到3/4处),如果不是则将地图缩放到最后一个点为中心的位置。

暂定或取消记录轨迹,就是利用clearInterval命令取消固定时间调用获取位置函数:

1
if(this.intervalID) { window.clearInterval(this.intervalID);}

3.系统展示

模块名称:首页

模块名称:地图数据管理

模块名称:地图模块


模块名称:用户信息管理模块

4.存在的不足

4.1 属性数据查看

进一步实现表格形式的属性数据查看,可以查看一副地图所具有的所有属性数据。还可增加点查功能,点击某个要素后弹出与该要素相关的属性数据。

4.2 分享功能

增加地图或者数据的分享功能,与pc端模式保持一致。还可以提供链接的形式分享,可供更多的用户查看、使用。

4.3 权限管理

考虑我们平台的受众群体,如果是开放的、面向大众的,可使用微信平台提供的接口,实现更智能的权限管理,只要用户微信授权后即可登录系统,免去了登录的繁琐过程。

4.4 改进样式写法

4.4.1 使用rem单位开发

系统开发时字体大小使用的是以px作为单位,而这对于不同屏幕分辨率的设备以及横竖屏的情况,大小始终保持不变,无法实现字体大小的屏幕自适应。在css3中引入了rem的概念,rem是相对于根元素<html>来设置字体大小。通过rem单位,实现字体的自适应。

4.4.2 使用icon font

图标主要使用的都是<img>标签,而且基本上都是使用单个图片文件,没有合并成CSS Sprite,这样增加了HTTP请求的次数。可以考虑使用IconFont技术,使用字体文件取代图片文件,这种方式减轻了HTTP请求的负担,而且文件更加容易编辑和维护。

React简介与应用实践

发表于 2018-10-10   |   分类于 框架应用   |  

1.React简介

  • 仅仅是UI
    许多人使用React作为MVC架构的V层。 尽管React并没有假设过你的其余技术栈, 但它仍可以作为一个小特征轻易地在已有项目中使用。
  • 虚拟DOM
    React为了更高超的性能而使用虚拟DOM作为其不同的实现。 它同时也可以由服务端Node.js渲染 - 而不需要过重的浏览器DOM支持。
    组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,组件的HTML结构并不会直接生成DOM,而是映射生成虚拟的JavaScript DOM结构,React又通过在这个虚拟DOM上实现了一个 diff 算法找出最小变更,再把这些变更写入实际的DOM中。这个虚拟DOM以JS结构的形式存在,计算性能会比较好,而且由于减少了实际DOM操作次数,性能会有较大提升。
  • 数据流
    React实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
    React中文文档链接http://reactjs.cn/react/index.html

2.为什么使用React

React是一个 Facebook 和 Instagram 用来创建用户界面的 JavaScript 库。很多人认为 React 是 MVC 中的 V(视图)。我们创造 React 是为了解决一个问题:构建随着时间数据不断变化的大规模应用程序。为了达到这个目标,React 采用下面两个主要的思想。

  • 简单
    仅仅只要表达出你的应用程序在任一个时间点应该长的样子,然后当底层的数据变了,React 会自动处理所有用户界面的更新。
  • 声明式
    数据变化后,React 概念上与点击“刷新”按钮类似,但仅会更新变化的部分。

3.数据呈现

用户界面能做的最基础的事就是呈现一些数据。React 让显示数据变得简单,当数据变化时,用户界面会自动同步更新。

快速开始

新建一个名为 hello-react.html 的文件,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello React</title>
<script type="text/javascript" src="http://fb.me/react-0.14.7.js"></script>
<script type="text/javascript" src="http://fb.me/JSXTransformer-0.14.7.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
var HelloWorld = React.createClass({
render: function() {
return (
<p>
Hello,<input type="text" placeholder="Your name here" />!
It is {this.props.date.toTimeString()}
</p>
);
}
});

setInterval(function() {
React.render(
<HelloWorld date={new Date()} />,
document.getElementById('example')
);
}, 500);
</script>
</body>
</html>

注意事项

  • ReactJs是基于组件化的开发,所以最终你的页面应该是由若干个小组件组成的大组件。
  • 可以通过属性,将值传递到组件内部,同理也可以通过属性将内部的结果传递到父级组件;要对某些值的变化做DOM操作的,要把这些值放到state中。
  • 为组件添加外部css样式时,类名应该写成className而不是class;添加内部样式时

    1
    2
    style={{opacity: this.state.opacity}}; //正确
    style="opacity:{this.state.opacity};" //错误
  • 组件名称首字母必须大写。

  • 变量名用{}包裹,且不能加双引号。

响应式更新(Reactive Updates)

在浏览器中打开 hello-react.html ,在输入框输入你的名字。你会发现 React 在用户界面中只改变了时间,你在输入框的输入内容会保留着,即使你没有写任何代码来完成这个功能。React 也为你解决了这个问题,做了正确的事。

我们想到的解决方案是React 是不会去操作 DOM 的,除非不得不操作 DOM 。它用一种更快的内置仿造的 DOM 来操作差异,为你计算出效率最高的 DOM 改变。

这个组件的输入被称为 props - “properties”的缩写。它们通过 JSX 语法进行参数传递。你必须知道,在组件里这些属性是不可直接改变的,也就是说 this.props 是只读的。

组件就像是函数

React 组件非常简单。你可以认为它们就是简单的函数,接受 props 和 state 作为参数,然后渲染出 HTML。正是由于它们如此简单,使得它们非常容易理解。

4.富交互性的动态用户界面

简单例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked? 'like': 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
React.render(
<LikeButton />,
document.getElementById('example')
);

事件处理与合成事件(Synthetic Events)

React 里只需把事件处理器(event handler)以骆峰命名(camelCased)形式当作组件的 props 传入即可,就像使用普通 HTML 那样。React 内部创建一套合成事件系统来使所有事件在 IE8 和以上浏览器表现一致。也就是说,React 知道如何冒泡和捕获事件,而且你的事件处理器接收到的 events 参数与 W3C 规范一致,无论你使用哪种浏览器。

如果需要在手机或平板等触摸设备上使用 React,需要调用React.initializeTouchEvents(true); 启用触摸事件处理。

幕后原理

在幕后,React 做了一些操作来让代码高效运行且易于理解。

Autobinding: 在 JavaScript 里创建回调的时候,为了保证 this 的正确性,一般都需要显式地绑定方法到它的实例上。有了 React,所有方法被自动绑定到了它的组件实例上。React 还缓存这些绑定方法,所以 CPU 和内存都是非常高效。而且还能减少打字!

事件代理 : React 实际并没有把事件处理器绑定到节点本身。当 React 启动的时候,它在最外层使用唯一一个事件监听器处理所有事件。当组件被加载和卸载时,只是在内部映射里添加或删除事件处理器。当事件触发,React 根据映射来决定如何分发。当映射里处理器时,会当作空操作处理。

组件其实是状态机(State Machines)
React 把用户界面当作简单状态机。把用户界面想象成拥有不同状态然后渲染这些状态,可以轻松让用户界面和数据保持一致。

React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。React 来决定如何最高效地更新 DOM。

State工作原理

常用的通知 React 数据变化的方法是调用 setState(data, callback)。这个方法会合并(merge) data 到 this.state,并重新渲染组件。渲染完成后,调用可选的 callback回调。大部分情况下不需要提供 callback,因为 React 会负责把界面更新到最新状态。

5.应用实例

以安信农业保险管理系统保单列表为例:(当前农保系统框架重构工作已全部完成)

源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
render() {
let handler4policy = {
handlerArrow: this.handlerArrow.bind(this),
handler4bd: {
handlerFolder: this.handlerFolder.bind(this),
handler4land: {
deleteLand: this.deleteLand.bind(this)
}
}
}
return (
<div className="item-wrap" style={this.props.css}>
<div className="item-search-wrap">
<input type="text" className='item-search-input' ref='search' value={this.state.search} placeholder="编号/证件号/姓名/电话" onChange={this.handlerInputChange.bind(this)} onKeyDown={this.handlerKeyDown.bind(this)}/>
<div className="item-search-btn" onClick={this.searchItem.bind(this)}>
<img className="item-search-logo" src="img/search.png" />
</div>
</div>
<div className="policy-add-btn" title="新建保单" onClick={this.handlerNewPolicy.bind(this)}>
<img className="item-insert-logo" src="img/add_2.png" />
<span className="item-insert-txt">新建保单</span>
</div>
<div className="item-contain">
<ul className = "item-ul">
{this.state.items.map((item, idx) => {
return (<PolicyMod key = {item.policy.CODING} {...this.config} {...item} {...handler4policy} index = {idx} />);
})}
</ul>
</div>
</div>
);
}

保单搜索

通过点击保单查询图标或输入框的Enter键盘事件触发SearchItem函数接受查询信息,进而以查询信息作为关键字调用农保保单查询接口获取保单列表的JSON数据,预处理数据后通过调用React框架的setState函数更新状态机完成列表的刷新操作,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
handlerKeyDown(event) {
let [target = event.target] = [event.srcElement];
if(event.keyCode === 13) {
this.search(target.value);
}
}

searchItem(event) {
this.search(this.refs.search.value);
}

search(val) {
this.setState({search: ''});
connect.fuzzyQuery(val, json => {
this.refreshList(json);
if(json.length > 0 && json[0].bdArr.length > 0) {
let bdxq = json[0].bdArr[0].bdxq;
Map.map.zoomTo(parseFloat(bdxq['X']), parseFloat(bdxq['Y']), { 'zl': 1 });
}
});
}

这里this.state.items为保单列表展示所提供的数据(JSON数据格式),一些可能改变列表内容的交互行为最终表现为改变该组件的state值(即组件的当前状态)即可达到轻松渲染页面的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
refreshList(json, fid) {
this.pretreat(json, fid);
Map.getVectorLandData();
this.setState({items: json});
}

pretreat(items, fid) {
Map.curListBdArr = [];
Map.exceptFIDArr = [];
for (let i = 0; i < items.length; i++) {
let item = items[i];
item.isOpen = this.config.defaultOpen;
for (let j = 0; j < item.bdArr.length; j++) {
let bd = item.bdArr[j];
bd.isOpen = this.config.defaultOpen;
Map.curListBdArr.push(bd.bdxq.ID);
for (let z = 0; z < bd.landArr.length; z++) {
let land = bd.landArr[z];
land.highlight = false;
if(fid && land.FID === fid) {
land.highlight = true;
}
let cp = this._calCenterPoint(land.XMIN, land.XMAX, land.YMIN, land.YMAX);
land.centerPoint = `${cp.x},${cp.y}`;
}
}
}
}

保单操作

当通过点击对话框中相应的事件完成对保单的添加、更新以及删除操作的响应时,利用获取到的事件调用列表组件的保单事件接受函数完成相应的业务操作并更新数据库,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
alterPolicy_ex(type, detail) {
const plTAB = config.policyTab;
this._handlerDateForm(detail);
let params = {Fields: [], Data: [[]]};
for(let key of Object.keys(detail)) {
if(key === 'CODING') {
params.Fields.unshift(key);
params.Data[0].unshift(detail[key]);
continue;
}
params.Fields.push(key);
params.Data[0].push(detail[key]);
}
if(type === 'INSERT') {
detail.USRID = sessionStorage.getItem('usrName');
detail.AREA = 0;
params.Fields.push('USRID', 'AREA');
params.Data[0].push(detail.USRID, detail.AREA);
let plJson = { policy: detail, bdArr: [], isOpen: true };
this.state.items.push(plJson);
toolUtil.recordAdd(config.dbName, plTAB, params, () => {
toolUtil.newalertDiv('添加成功');
this.setState({items: this.state.items});
});
} else {
this.state.items.forEach(item => {
if (item.policy.CODING === detail.CODING) {
item.policy = detail;
}
});
toolUtil.recordUpdate(config.dbName, plTAB, params, () => {
toolUtil.newalertDiv('保存成功');
this.setState({items: this.state.items});
});
}
}

deletePolicy_ex(coding) {
let curInsFeas = Map.curWindowInsureFeas;
Map.curWindowInsureFeas = curInsFeas.filter(fea => {
if (fea.fields.CODING == coding) Map.insure_Featurelayer.removeFeature(fea);
return (fea.fields.CODING != coding);
});
this.state.items = this.state.items.filter(item => item.policy.CODING !== coding);
this.setState({items: this.state.items});
connect.deletePolicyByCoding(coding, () => {
toolUtil.newalertDiv('删除成功');
});
}

同样的,在处理不同的事件操作过程中通过改变组件的state值(这里是state.items),添加时push一条记录、更新替换一条记录、以及删除时剔除一条记录的方式,统一更改state值,再一次调用setState函数完成保单列表的刷新工作,渲染保单。最后根据不同的需求增删改操作数据库,完成保单的操作任务。

标的操作

在完成对标的的添加、更新以及删除操作时,利用获取到的事件调用列表组件的标的事件接受函数完成相应的业务操作并更新数据库,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
alterBd_ex(type, detail, point) {
const bdTAB = config.bdTab;
let params = {Fields: [], Data: [[]]};
for(let key of Object.keys(detail)) {
if(key === 'ID') {
params.Fields.unshift(key);
params.Data[0].unshift(detail[key]);
continue;
}
params.Fields.push(key);
params.Data[0].push(detail[key]);
}
if(type === 'INSERT') {
detail.AREA = 0;
params.Fields.push('AREA');
params.Data[0].push(detail.AREA);
let bdJson = { bdxq: detail, landArr: [], isOpen: true };
this.state.items.forEach(item => {
if (item.policy.CODING === detail.CODING) {
item.bdArr.push(bdJson);
}
});
toolUtil.recordAdd(config.dbName, bdTAB, params, () => {
toolUtil.newalertDiv('添加成功');
Map.map.zoomTo(parseFloat(point.X), parseFloat(point.Y), { zl: 1 });
let SQL = { 'fields': 'max(ID)', 'lyr': bdTAB, 'filter': '' };
toolUtil.recordQuery(config.dbName, SQL, msg => {
bdJson.bdxq.ID = msg[0]['max(ID)'];
this.setState({items: this.state.items});
});
});
} else {
this.state.items.forEach(item => {
if (item.policy.CODING === detail.CODING) {
let bdArr = item.bdArr;
bdArr.forEach(bd => {
if(bd.bdxq.ID === detail.ID) {
bd.bdxq = detail;
}
});
}
});
toolUtil.recordUpdate(config.dbName, bdTAB, params, () => {
toolUtil.newalertDiv('保存成功');
Map.map.zoomTo(parseFloat(point.X), parseFloat(point.Y), { zl: 1 });
this.setState({items: this.state.items});
});
}
}

同保单操作,在处理不同的事件操作过程中依然通过改变组件的state值,调用setState函数完成保单列表的刷新工作。最后根据不同的需求增删改操作数据库,完成标的的操作任务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
deleteBd_ex(coding, bdid, area) {
let curInsFeas = Map.curWindowInsureFeas;
Map.curWindowInsureFeas = curInsFeas.filter(fea => {
if (fea.fields.BDID === bdid) Map.insure_Featurelayer.removeFeature(fea);
return (fea.fields.BDID !== bdid);
});
this.state.items.forEach(item => {
if (item.policy.CODING == coding) {
item.bdArr = item.bdArr.filter(bd => bd.bdxq.ID !== bdid);
item.policy.AREA = (parseFloat(item.policy.AREA) - area).toFixed(2);
connect.updateArea4Policy(coding, item.policy.AREA);
}
});
this.setState({items: this.state.items});
connect.deleteBdById(bdid, () => {
toolUtil.newalertDiv('删除成功');
});
}

地块操作

1.添加地块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
insertLand_ex(selectedfea) {
let [fields, params, land = {BDID: curbdid, CODING: curcoding}] = [selectedfea.fields, {Fields: landRelFields, Data: [[]]}];
landRelFields.forEach((fid) => {
if(fields[fid]) {
land[fid] = fields[fid];
params.Data[0].push(fields[fid]);
} else {
fid === 'BDID' && params.Data[0].push(curbdid);
fid === 'CODING' && params.Data[0].push(curcoding);
}
});
let cp = this._calCenterPoint(land.XMIN, land.XMAX, land.YMIN, land.YMAX);
land.centerPoint = `${cp.x},${cp.y}`;

selectedfea.addFields({'BDID': curbdid, 'CODING': curcoding});
Map.curWindowInsureFeas.push(selectedfea);
Map.curWindowInsureFeas.forEach(fea => {
if(fea.fields.BDID == curbdid) {
Map.insure_Featurelayer.addFeature(fea);
}
});
if(!toolUtil.isInArr(curbdid, Map.curListBdArr)) {
Map.curListBdArr.push(curbdid);
}

let area = 0;
this.state.items.forEach((item) => {
if (item.policy.CODING === curcoding) {
let bdArr = item.bdArr;
bdArr.forEach((bd) => {
if (bd.bdxq.ID === curbdid) {
bd.isOpen = true;
bd.landArr.push(land);
area = parseFloat(land.SHPAREA) / 666.67;
bd.bdxq.AREA = (parseFloat(bd.bdxq.AREA) + area).toFixed(2);
connect.updateArea4Bd(bd.bdxq.ID, bd.bdxq.AREA);
}
});
item.policy.AREA = (parseFloat(item.policy.AREA) + area).toFixed(2);
connect.updateArea4Policy(item.policy.CODING, item.policy.AREA);
}
});
this.setState({items: this.state.items});
toolUtil.recordAdd(config.dbName, config.landRelTab, params);
}

2.删除地块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
deleteLand(fid, bdid, coding) {
let area = 0;
Map.curWindowInsureFeas = Map.curWindowInsureFeas.filter(fea => {
if (fea.fields.FID === fid) Map.insure_Featurelayer.removeFeature(fea);
return (fea.fields.FID !== fid);
});
this.state.items.forEach((item) => {
if (item.policy.CODING === coding) {
let bdArr = item.bdArr;
bdArr.forEach((bd) => {
if (bd.bdxq.ID === bdid) {
bd.landArr = bd.landArr.filter(land => {
if (land.FID === fid) area = parseFloat(land.SHPAREA) / 666.67;
return land.FID !== fid;
});
bd.bdxq.AREA = (parseFloat(bd.bdxq.AREA) - area).toFixed(2);
connect.updateArea4Bd(bd.bdxq.ID, bd.bdxq.AREA);
}
});
item.policy.AREA = (parseFloat(item.policy.AREA) - area).toFixed(2);
connect.updateArea4Policy(item.policy.CODING, item.policy.AREA);
}
});
this.setState({items: this.state.items});
let params = {
'Fields': 'FID',
'Data': [fid]
};
toolUtil.recordDelete(config.dbName, config.landRelTab, params);
}

地块操作任务需要记录点选地块的要素信息(包括空间、属性信息)或地块的FID,在地图上高亮显示点选的保险地块后调用列表组件的接收函数将该要素信息添加到state中,或在state中剔除,更新组件state完成地块的添加或删除操作。最后更新数据库完成录入工作。

6.与其他框架的比较

React与Angular

  • Reactjs作为view本身非常独立,不仅可以在浏览器上用,还可以在server端结合nodejs做模板。
  • 除了独立,Reactjs还很灵活小巧,用起来像拼lego的积木,一个component接着另一个component。
  • 在性能方面,由于运用了virtual dom技术,Reactjs只在调用setstate的时候会更新dom,而且还是先更新virtual dom,然后和实际dom比较,最后再更新实际dom。这个过程比起angularjs, knockoutjs的bind方式来说,一是更新dom的次数少,二是更新dom的内容少,速度肯定是快了的。另外Reactjs用了jsx,这个相当于半个新语言了。

  • angularjs是一个m-v-whateever framework。framework的一个特点就是很全面,除了m-v-whatever面面俱到,它还自带了很多$开头的service,$http, $route, $q(defer),$cookie等等。

  • angularjs的架构清晰,分工明确,整个框架充满了DI的思路,耦合性非常低,对象都是被inject的,也就是说每个对象都可以轻易被替换而不影响其他对象。

React与Polymer

Polymer沿袭了正统的HTML+CSS+JS思路进行革新,很多组件化的功能靠浏览器自身的功能去支持,用浏览器原生的接口去做组件的集成,使用了效率最高的Vanilla JS ,易学易用。但是在兼容性方面不如React,React利用jsx集合Babel转码工具等,较好的解决了兼容性问题支持ie8及以上。

React与jQuery

jQuery的思路是以dom为中心,所以的操作都在围绕着dom的变化来操作。也就是jQuery的核心思想是dom可变。

React认为页面dom不可变,所以当状态和属性发生变化时会re-render dom。React会根据新的状态和属性生成新的VirtualDOM Tree然后和旧的VirtualDOM Tree做对比(类似于版本控制的机制)。通过对比计算出最小的更新代价,然后将这些更新的方法进入队列。

Polymer介绍

发表于 2018-10-10   |   分类于 框架应用   |  

1 Polymer简介

Polymer(聚合物,设计理念:材料学设计规范)
Polymer是google开发的web components方式的前端UI控件库

历史
2013年google I/O大会发布0.5开发者预览版
2015年 google I/O大会发布1.0版本
目前已更新到1.2.3版本

web components 是什么?
web组件就是web的一个一个元素标签, 如input标签,img标签,video标签等等。 web componts的概念就是把所有可重用的东西封装成元素组件, 下次要用,自己使用自己写好的标签即可。

polymer给大家提供了封装自定义标签的方法,它自己也有很多已经封装的标签
polymer的理念是一切功能皆元素, 即使是ajax, 也是元素,core-ajax标签可以发起ajax请求, 文档地址:http://www.polymer-project.org/docs/elements/core-elements.html#core-ajax
polymer已经有了一个组件库,里面有很多已经封装好的组件。

2 快速实践

新建newTag.html文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<link rel="import" href="polymer/polymer.html">
<dom-module id="element-name">
<template>
<style>
/* 组件元素CSS样式 */
</style>
<!—该组件的本地DOM-->
<div on-click=”handleClick”>{{greeting}}</div> <!—在本地DOM上绑定数据-->
</template>
</dom-module>

<script>
// 注册元素
Polymer({
is: "element-name",//自定义元素的名称必选用连接符

// 给元素添加属性和方法
properties: {
// 为元素声明公共api
greeting: {
type: String,
value: "Hello!"
}
},
handleClick: function(event) {
/*事件逻辑*/
}
});
</script>

详细说明

1、如果使用该组件,则在html文件中导入即可

1
<link rel="import" href="newTag.html">

2、声明周期的回调函数

  • ceated
  • attached
  • detached
  • attributeChanged

3、本地DOM的初始化顺序

  • created callback
  • local DOM initialized
  • ready callback
  • factoryImpl callback
  • attached callback

4、通过dom-module定义一个本地DOM,及自定义标签,该标签的id为该自定义标签的名称<dom-module id="element-name">,名称必须用-连字符。
5、在<dom-module>中放置<template>,polymer将会自动克隆template标签中的内容到自定义标签中(即本地DOM)。
6、Polymer({ })实现组件。
7、可以在组件中定义样式,通过在template内定义style实现。
8、事件监听 on-eventname 和addEventlistener的区别。

  • polymer提供了on-eventname属性来对事件进行监听, 如监听按钮的点击事件:

    1
    <paper-button id="button" label="flat button" on-click="{{buttonClick}}"></paper-button>
  • 另外还可以用addEventlistener监听事件,如

    1
    2
    3
    4
      this.$.button.addEventlistener('click',function(){
    alert('click');
    console.log(this);
    });

在两种监听方法是有区别的。

  • on-eventname 方式监听, 在监听函数中 this 指向的是当前polymer对象。可以用this来获得当前polymer对象的其他属性。
  • 而addEventlistener 在监听函数中 this 是当前元素。

3 拓展–标准HTML 5组件实现API

• Shadow DOM:Shadow DOM API 支持您将元素添加到通过常用方法(比如document.getElementById())无法访问的 DOM 树。Shadow DOM 中的元素隐藏在暗处;它们对 DOM 树其他部分实际上是不可见的,在默认情况下,它们不受周围文档中的 CSS 的影响。
• 模板:HTML5 模板是一个惰性文档片段。当您需要显示这些片段时,可以 创建该模板,让片段出现在 DOM 树中。这些模板允许您封装那些您可以创建和定制的 HTML、JavaScript 和 CSS。(相当于polymer中的template)
• 定制元素定制元素是组件的标签。定制组件的标签必须包含一个连字符(例如 ),除此之外,它们与内置 HTML 标签没什么区别。
• HTML 导入:HTML 导入允许您从一个 HTML 文件中导入另一个,这使得您可以在其自身文件中实现定制组件。

这些 API 目前仍正开发中。撰写文本之时,还没有浏览器支持所有这些 API。因此,如果现在开始实现 HTML5 标准组件,那么可以从 Polymer 和 X-Tags 这两个开源项目中进行选择,它们提供了缺失的功能。

CSS3--font-face使用

发表于 2018-10-10   |   分类于 前端技术   |  

1.介绍

  • @font-face是CSS3中的一个模块,主要是把自己定义的Web字体嵌入到你的网页中,不用担心兼容性,@font-face在IE4中都支持。
  • 如果是用字体做logo,英文的话字体和图片占用大小差不多,但是中文的字体包一般比较大,最好还是使用图片的形式。

为什么要将icon做成字体?

字体文件小,一般20-50kb; 容易编辑和维护,尺寸和颜色可以用css来控制; 透明完全兼容IE6;当然,Icon Font也是有缺点的,由于是字体,所以只支持图片上是纯色的,多种颜色的就不支持了。

各个浏览器对字体格式的支持是最大的区别:

webkit/safari:支持TrueType/OpenType(.ttf),OpenType PS(.otf),iOS4.2+支持.ttf,iOS 4.2以下只支持SVG字体;
Chrome:除webkit支持的以外,从Chrome 6开始,开始支持woff格式;
Firefox:支持.ttf和.otf,从Firefox 3.6开始支持woff格式;
Opera:支持.ttf、.otf、.svg。Opera 11开始支持WOFF; IE:只支持eot格式,IE9开始支持woff。

2.快速实践

  • 下载字体需要格式为.tff格式的字体文件
  • 搜索Webfont Generator,或者直接使用该网站提供的服务。这很简单,进入网站后选择.tff字体文件上传,勾选同意的复选框,点击Generate web font,点击Download Package下载,解压缩文件。
  • 使用
    新建index.css
1
2
3
4
5
6
7
8
9
10
11
12
@font-face {
font-family: 'Happy-Camper-Regular';
src: url('../fonts2/Happy-Camper-Regular.eot');
src: url('../fonts2/Happy-Camper-Regular.eot?#iefix') format('embedded-opentype'), url('../fonts2/Happy-Camper-Regular.woff') format('woff'), url('../fonts2/Happy-Camper-Regular.ttf') format('truetype'), url('../fonts2/Happy-Camper-Regular.svg#SingleMaltaRegular') format('svg');
font-weight: normal;
font-style: normal;
}

h2.demo {
font-size: 100px;
font-family: 'Happy-Camper-Regular'
}
1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>字体</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h2 class="demo">hello world!You are my Destiny</h2>
</body>
</html>

3.字体icon

使用某些字体,如:WebSymbols-Regular百度云下载地址,Guifx字体,包括现在开源的比较流行的Font Awesome,使用方法同上。在html文件中如下示例:

1
2
3
4
5
<span>A</span>
<span>B</span>
<span>C</span>
<span>D</span>
<span>F</span>

每一行显示的是其对应的图标

参考文献:

  • 下载字体的地方
  • CSS3 @font-face
  • @font-face制作Web Icon

附在线icon font字体图标库:
http://www.weste.net/2013/12-13/94697.html
http://www.iconfont.cn/?spm=a313x.7781069.0.0.pICV51 阿里巴巴矢量图标
https://www.fontsquirrel.com/tools/webfont-generator
http://fontello.com/
https://icomoon.io/app/#/select
http://glyphicons.com/
http://fontawesome.io/

Hello World

发表于 2016-06-06   |  

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

123
Leo_婷子酱

Leo_婷子酱

30 日志
6 分类
24 标签
GitHub
© 2018 Leo_婷子酱
由 Hexo 强力驱动
主题 - NexT.Pisces