JiM-W

keep Moving


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

html5 Drag

发表于 2016-11-22 | 分类于 html drag

1,全屏API:DOM元素支持全屏,HTML5的标准写法是 ele.requestFullScreen( ), 即可使DOM元素全屏;但是由于该方法处于不够完善,所以需要写各个浏览器的兼容代码;

1
2
3
4
5
6
7
8
9
if(this.webkitRequestFullScreen){
this.webkitRequestFullScreen();
}else if(this.mozRequestFullScreen){
this.mozRequestFullScreen();
}else if(this.requestFullScreen){
this.requestFullScreen();
}else if(this.msRequestFullscreen){
this.msRequestFullscreen();
}

2,拖拽API:首先来看有哪些拖放(drag和drop)的事件,如果要是元素可以拖拽,

首先要给该元素设置 draggable = true 属性,保证该元素可以被拖放.(img标签默认支持拖放,div默认不支持拖放)

拖拽元素的事件如下:

  • ondrag 当拖动元素的时候运行脚本
  • ondragstart 当拖动操作开始时候运行脚本
  • ondragend 当拖动操作结束的时候运行脚本

目标元素的事件如下:

  • ondragover 当元素被拖动至有效拖放目标上方时执行脚本
  • ondragenter 当元素被拖动至有效拖动目标时执行脚本
  • ondragleave 当元素离开至有效拖放目标是运行脚本
  • ondrop 当被拖动元素正在被放下的时候运行脚本

注意如果想要使目标元素可以被放进来拖放的元素,因为默认地,无法将数据/元素放置到其他元素中。如果需要设置允许放置,我们必须阻止对元素的默认处理方式。此时需要对目标元素进行处理,调用dragover阻止默认事件 的方法:

1
2
3
目标元素.ondragover = function(event){
event.preventDefault() ;
}

3 代码演示

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
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
html,
body {
height: 100%;
}
body {
margin: 0;
display: flex;
justify-content: space-around;
align-items: center;
}
div {
width: 400px;
height: 400px;
border: 1px solid #000;
}
.left {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
div>img {
width: 70px;
height: 70px;
margin: 10px;
background-color: ;
}
/* 使用css来修改 定义一个 高亮的颜色 */
.right.active {
background-color: lightblue;
}
</style>
</head>
<body>
<div class="left">
<img src="imgs/lofter_1_noval_icon_ (1).jpg" alt="">
<img src="imgs/lofter_1_noval_icon_ (2).jpg" alt="">
<img src="imgs/lofter_1_noval_icon_ (3).jpg" alt="">
</div>
<div class="right"></div>
</body>
</html>
<script>
// .right 盒子 元素移入 颜色高亮
document.querySelector('.right').ondragenter = function () {
// this.style.background = 'lightgray';
this.classList.add('active');
// $(this).addClass('active');
}
// .right 移出 颜色还原
document.querySelector('.right').ondragleave = function () {
// 颜色 就是 直接设置透明
// this.style.background = 'transparent';
// this.style.background = 'rgba(0,0,0,0)';
this.classList.remove('active');
}
// 为了能够触发drop 必须设置如下代码,给目标元素设置阻止默认处理方式,允许元素可以被放置
document.querySelector('.right').ondragover = function (event) {
event.preventDefault();
}
// drop .right盒子绑定
// img 拖拽开始的 时候 保存为 全局变量
var imgs = document.querySelectorAll('.left>img');
// 当前移动的 img
var moveImg = undefined;
// 循环绑定,给每个拖拽元素设置拖拽事件,每个元素被拖拽时触发该事件
for(var i=0;i<imgs.length;i++){
imgs[i].ondragstart = function(){
// 保存为全局变量
moveImg = this;
// 打印是否保存
console.log(moveImg);
}
}
document.querySelector('.right').ondrop = function () {
// moveImg.ondrop = function () {
console.log('进来了');
// 将 丢进来的 元素 设置为 子元素
// 获取丢进来的元素 在拖拽img的时候 将当前拖拽的img 存起来获取保存的img
// 通过全局变量 moveImg 添加给自己
document.querySelector('.right').appendChild(moveImg);
// 还原 自己的颜色
this.classList.remove('active')
}
</script>

JSON operate

发表于 2016-11-21 | 分类于 javascript

JSON数据处理的方法

1 json数据格式:

  • 以键值对的形式存在 json={“key”:”value”,”key1”:”value1”,”key2”:”value2”};
  • key对应的值可以使数组或者对象 json={“key” : { } , “key1” : [ ] , “key2” : function(){ } } ;
  • json是一种规范,一种数据格式的规范
  • json实际上是字符串

2 json数据格式,”存前读后”,也就是说存储json格式的数据之前,要进行将其转化为字符串,读取的时候,要转化为对象

JSON.stringify() 将一个对象解析成字符串 将JavaScript值转换为JSON字符串

JSON.parse() 将一个字符串解析成对象 ,构造由字符串描述的JavaScript值或对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
var myJson={"UserName":"Jim"};
console.log(myJson);//Object {UserName: "Jim"}
var strMyJson = JSON.stringify(myJson);//将myJson存进去,记得JSON.stringify转成字符串
console.log(strMyJson);// 字符串 '{UserName: "Jim"}'
console.log(typeof strMyJson);//string
var objMyJson=JSON.parse(strMyJson);//取出来的是字符串,记得JSON.parse还原为对象
console.log(objMyJson);//Object {UserName: "Jim"}
console.log(typeof objMyJson);//object
var data = [{"name":"jhon"},{"age":16}];//数组也可以
var strData = JSON.stringify(data);
console.dir(strData);
console.dir(typeof strData);
</script>

3 JSON.parse用法在JSON.parse and eval 博文已经总结过

4 JSON.stringify()详解 (参阅MDN)

语法 返回值是一个JSON格式的字符串

1
JSON.stringify(value[, replacer [, space]])
  • value是要序列化为一个JSON字符串的值
  • replacer可选参数
    • 如果该参数是一个函数,那么在序列化的过程中的被序列化的每个属性都会经过该函数的转换和处理
    • 如果该参数是一个数组,那么只有包含在该数组中的属性名才能被最终序列化为JSON字符串
    • 如果该参数为null或者未提供, 那么对象的所有属性都会被序列化
  • space 可选参数,用于梅花输出
    • 如果该参数是一个数字,代表有多少个空格,上限为10 ,如果该数字小于1,则没有空格
    • 如果该参数为null或者没有提供将没有空格

注意事项

  • 字符串,数字,布尔类型的数据值会被直接 转化为原始值
  • undefined 函数 以及symbol值
    • 在数组中出现的时候,会被转化为null
    • 作为对象的属性值出现的时候,整个键值对都会被忽略
  • 不可枚举的属性不会被序列化为字符串

走几个demo便于理解和记忆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var obj = Object.create({ foo: 1 }, { // foo is on obj's prototype chain.
bar: {
value: 2 // bar is a non-enumerable property.默认值false
},
baz: {
value: 3,
enumerable: true // baz is an own enumerable property.
}
});
console.log(JSON.stringify(obj));//'{"baz":3}'
console.log(JSON.stringify({}));//'{}'
console.log(JSON.stringify(false));//"false"
console.log(JSON.stringify(4));//"4"
console.log(JSON.stringify('foo'));//"foo"
console.log(JSON.stringify(['foo',2,true]));//'["foo",2,true]'
console.log(JSON.stringify([undefined,Array,Symbol("")]));//'[null,null,null]'
console.log(JSON.stringify({x:undefined,y:Array,z:Symbol("")}));//'{}'

replacer函数

  • 如果返回一个 Number 转换成相应的字符串被添加入JSON字符串。
  • 如果返回一个 String, 该字符串作为属性值被添加入JSON。
  • 如果返回一个 Boolean, “true” 或者 “false”被作为属性值被添加入JSON字符串。
  • 如果返回任何其他对象,该对象递归地序列化成JSON字符串,对每个属性调用replaceer方法。除非该对象是一个函数,这种情况将不会被序列化成JSON字符串。
  • 如果返回undefined,该属性值不会在JSON字符串中输出。
1
2
3
4
5
6
7
8
9
10
var obj = {name:'Jhon',age:19,gender:"man"};
function replacer (key,value){
if(typeof value === 'number'){
return undefined;
}
return value ;
}
var jsonString = JSON.stringify(obj,replacer);
console.log(jsonString);
//'{"name":"Jhon","gender":"man"}'
1
2
3
var obj = {name:'Jhon',age:19,gender:"man"};
var jsonString = JSON.stringify(obj,['age','other']);//多余的会被忽略
console.log(jsonString);//'{"age":19}' ;

Angular Js directive

发表于 2016-11-21 | 分类于 javascript

建议大家看angular英文文档,然后实践出真知

1 angular directive的自定义用法 我们在定义一个指令的时候使用驼峰法来命名一个指令,例如 runoobDirective, 但在使用它时需要以 -分割, runoob-directive;

先来看下自定义指令的语法结构

首先定义指令前需要首先定义一个模块

1
var app = angular.module('app',[]);//定义一个模块

在定义了模块之后,可以在定义指令

1
2
3
app.directive('directiveName',function(){
return config
})

return的配置参数有很多,接下来一一进行分析

1.1 限制使用 restrict 值为字符串 可以的值有 ECMA E设置指令可以通过元素的形式进行调用 A 设置指令可以通过属性的形式调用 M设置指令可以通过注释的形式调用 C设置指令可以通过类名进行调用;

默认值是EA ,表示我们定义的指令可以通过元素名或者属性的形式进行调用

你可以限制你的指令只能通过特定的方式来调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- E (element) -->
<directiveName></directiveName>
比如<ng-view></ng-view>等
<!-- A (attribute) -->
<div directiveName="expression"></div>
比如<div ng-init="name= 'Jhon'"></div>
<div ng-hide="name= 'Jhon'"></div> 等
<!-- C (class) -->
<div class="directiveName"></div>
<!-- M(comment) -->
<!--directive:directiveName expression-->

1.2 priority 默认值为0

数字,可选参数,致命指令的优先级,若在单个DOM元素上有多个指令,则优先级高的先执行。

当然,设置指令的优先级不太常用,但是比较特殊的例子是,内置指令ng-repeat的优先级为1000,而ng-init的优先级为 450。

1.3 terminal

布尔型,可选参数,可以被设置为true或者false,若设置为true,则优先级低于此指令的其他指令则无效,不会被调用优先级相同任然会执行。

1.4. template

字符串或者函数,可选参数。 其中字符串可以是html标签,可以是一个页面,也可以是一个简单的字符串比如 “this is str”

  • 如下栗子我们简单的定义了一个指令,template是字符串的形式
1
2
3
4
5
6
app.directive('hello',function(){
return {
//默认restrict是EA
template:'<div>try your best</div>'
}
})

然后可以使用该指令,通过属性或者元素的方式进行指令的使用

1
2
<div hello></div>
<hello></hello>

显示结果如下

1
2
try your best
try your best
  • 如下栗子我们定义的一个指令,template是函数的形式,function函数接受两个参数,第一个是element,表示使用此指令的元素,attrs是 实例的属性,它有一个元素上所有的属性组成集合
1
2
3
4
5
6
7
8
9
app.directive('hello1',function(){
return {
template:function(ele,attr){
console.log(arguments);
//为了便于说明函数传入的参数ele和attr到底代表的是哪些,我们可以打印出来看下具体的结果
return '<div>'+'hello '+attr.info+'</div>'
}
}
})

然后可以使用该指令,通过属性或者元素的方式进行指令的调用,可以发现第一个调用输出arguments,ele参数代表hello1元素,attr参数代表hello1上面的属性的集合 ,第二次输出arguments,ele代表div元素,attr参数代表div上面的所有的属性的集合

1
2
<hello1 info = 'Jhon'></hello1>
<div hello1 info='JiM'></div>

显示结果如下:

1
2
hello Jhon
hello JiM

html的结构如下

1
2
3
4
5
6
<hello1 info = 'Jhon'>
<div>hello Jhon</div>
</hello1>
<div hello1 info='JiM'>
<div>hello JiM</div>
</div>

1.5 replace 布尔型,默认值为false,设置为true的时候,表示可以用自定义的模板内容的标签替换自定义的元素标签。在上例子的基础上,变化如下,大家可以对比下上述两者html的结构的区别

1
2
3
4
5
6
7
8
9
app.directive('hello1',function(){
return {
replace:true,
template:function(ele,attr){
console.log(arguments);
return '<div>'+'hello '+attr.info+'</div>'
}
}
});

html结构

1
2
<div hello1="" info="JiM">hello JiM</div>
<div info="Jhon">hello Jhon</div>

1.6 templateUrl (字符串或者函数),可选参数,可以是

(1)一个代表HTML文件路径的字符串

(2)一个函数,可接受两个参数tElement和tAttrs(大致同上)

1.6.1 templateUrl接受一个字符串

index.html页面中有如下代码

1
2
3
4
<script type='text/ng-template' id='courage.html'>
//注意,模板文件的type属性必须是 ng-template ,表示以angular的规则进行模板的解析
<p>that is awesome to learn more about IT </p>
</script>

我们可以定义一个指令

1
2
3
4
5
6
7
app.directive('courage',function(){
return {
templateUrl:"courage.html",
replace:true,
restrict:'E'
}
})

调用指令

1
<conrage></conrage>

页面显示的html结构如下(注意restrict和replace属性的设置对于显示的影响)

1
<p>this is awesome to learn more about IT </p>

1.6.2 templateUrl接受一个函数

index.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
<body ng-app = 'myApp'>
<div ng-controller = 'myCtrl'>
<p courage type='one'></p>
<p courage type='two'></p>
</div>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myCtrl',['$scope',function($scope){
$scope.info = {
name : 'Jhon',
age : '19'
}
}])
app.directive('courage',function(){
return {
templateUrl : function(ele,attr){
console.log(arguments);
return 'courage'+ attr.type+'.html';
}
}
})
</script>
</body>

courageone.html

1
2
3
<body>
<p>this is courage1:`{{info.name}}`</p>
</body>

couragetwo.html

1
2
3
<body>
<p>this is courage2:`{{info.age}}`</p>
</body>

1.7 scope 默认值是false

false表示继承父作用域的值,且不进行隔离,子作用域和父作用域的改变都将影响变量的值;

true表示继承父作用域的值,但是进行隔离,这种效果和设置两个控制器的效果是一样的;

{}:没有继承父亲的值,所以儿子的值为空,改变任何一方的值都不会影响另一方,这就是不继承且隔离;

当想要创建一个可重用的组件时,隔离作用域是一个很好的选择,通过隔离作用域,我们可以确保指令是独立的,并且可以轻松的插入到任何HTML APP中,并且这种做法防止了父作用域被污染。

先来看下作用域,我们知道,每定义一个控制器就会形成一个scope对象,该对象可以表示一个作用域,并且继承了父作用域的数据;我们从下面的例子可以改变输入的名字,

  • 子作用域继承了父作用域的变量
  • 子作用域和父作用域的变量的改变是相互独立的,也就是说子作用域是继承且隔离的

1.7.1 先来看下controller控制器下面的作用的效果,子作用域和父作用域是继承且隔离的效果,子作用域的变量的变化不会污染到父作用域;

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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src="angular.js"></script>
</head>
<body ng-app = 'app'>
<div ng-controller = 'parent' >
<input type="text" ng-model = 'name' placeholder='please input your name'/>
parent:`{{name}}`
age:`{{age}}`
<div ng-controller = 'child'>
<input type="text" ng-model = 'name' placeholder='please input your name'/>
child:`{{name}}`
age :`{{age}}`
</div>
</div>
<script>
var app = angular.module('app',[]);
app.controller('parent',['$scope',function($scope){
$scope.name = "Jhon";
$scope.age = 19 ;
}]);
app.controller('child',['$scope',function($scope){
$scope.name = "JiM";
}]);
//这种情势下的scope作用域是继承且隔离的,子作用域内的变量的改变不会对父作用域内的变量有任何的影响
</script>
</body>
</html>

1.7.2 再来看下我们自定义directive的时候的scope不同的设置情况的效果

false的情况(或者没有设置的时候默认的情况),子作用域会污染父作用域的变量,继承且不隔离

true的情况,和1.7.1controller的效果一样,继承且隔离,这种情况下也就是一般的原型继承的情况

{ } 的情况,表示不继承且隔离

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
<body ng-app = 'app'>
<div ng-controller = 'parent' >
<input type="text" ng-model = 'name'/>
parent:`{{name}}`
<child></child>
</div>
<script>
var app = angular.module('app',[]);
app.controller('parent',['$scope',function($scope){
$scope.name = "Jhon";
}]);
app.directive('child',function(){
return {
replace:true ,//默认值是false
restrict:'EA',
scope:false,
template:''+
'<div>'+
'<input type="text" ng-model = "name"/>'+
`'child:{{name}}'`+
'</div>'
}
});
//这种情势下的scope作用域是继承且隔离的,子作用域内的变量的改变不会对父作用域内的变量有任何的影响
</script>
</body>

1.7.3 当我们将scope设置为{ } 的时候,此时子作用域无法再访问父作用域的变量值,这个时候需要我们做出一些调整,让子作用域可以访问父作用域的变量,但是不会污染父作用域

  • 采用 @ 进行单向绑定,也就是说,改变父作用域的name的值,directive里面的name也会改变,但是改变隔离区directive里面的name,父作用域里面的name是不会发生改变的;也就是达到继承且隔离的效果
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
<body ng-app = 'app'>
<div ng-controller = 'parent' >
<input type="text" ng-model = 'name'/>
parent:`{{name}}`
<!--<child name="{{name}}"></child>-->
<child your-name=`"{{name}}"`></child>
</div>
<script>
var app = angular.module('app',[]);
app.controller('parent',['$scope',function($scope){
$scope.name = "Jhon";
}]);
app.directive('child',function(){
return {
replace:true ,//默认值是false
restrict:'EA',
scope:{
//如果绑定的隔离作用域属性名与元素的属性名相同,则可以采用缺省写法
// name:'@' //对应<child name="{{name}}"></child>
name:"@yourName"
},
template:''+
'<div>'+
'<input type="text" ng-model = "name"/>'+
`'child:{{name}}'`+
'</div>'
}
});
//这种情势下的scope作用域是继承且隔离的,子作用域内的变量的改变不会对父作用域内的变量有任何的影响
</script>
</body>

此时template生成的html结构如下

1
2
3
<div your-name="Jhon" class="ng-binding ng-isolate-scope">
<input type="text" ng-model="name" class="ng-valid ng-not-empty ng-dirty ng-touched">child:Jhon
</div>
1
2
3
4
5
6
//我们可以大致的模拟下ng-controller的实现原理
app.directive("myController", function(){
return {
scope: true, //scope设置为true,
controller: '@'
}});
  • 采用 = 进行双向绑定,也就是说,改变父作用域的name的值,directive里面的name也会改变,同样改变隔离区directive里面的name,父作用域里面的name是也会发生改变的;此时达到了 继承且不隔离的效果
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
<body ng-app = 'app'>
<div ng-controller = 'parent' >
<input type="text" ng-model = 'name'/>
parent:`{{name}}`
<child name="name"></child>
<!--需要注意的一点是和<child name="{{name}}"></child>的写法不同,不然效果出不来-->
</div>
<script>
var app = angular.module('app',[]);
app.controller('parent',['$scope',function($scope){
$scope.name = "Jhon";
}]);
app.directive('child',function(){
return {
replace:true ,//默认值是false
restrict:'EA',
scope:{
//
name:'='
},
template:''+
'<div>'+
'<input type="text" ng-model = "name"/>'+
`'child:{{name}}'`+
'</div>'
}
});
//这种情势下的scope作用域是继承且隔离的,子作用域内的变量的改变不会对父作用域内的变量有任何的影响
</script>
</body>

此时template生成的html结构如下

1
2
3
<div name="name" class="ng-binding ng-isolate-scope">
<input type="text" ng-model="name" class="ng-valid ng-not-empty ng-dirty ng-touched ng-valid-parse">child:Jhon
</div>

上面这个栗子当时选择的不好,关于name容易混淆,这里在写一个清晰一点的

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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body ng-app = 'myApp'>
<div ng-controller = 'stuInfoCtrl'>
<stu-info info = 'jhon'></stu-info>
<stu-info info = 'merry'></stu-info>
</div>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('stuInfoCtrl',['$scope',function($scope){
$scope.jhon = {
name : "Jhon",
age : 17
}
$scope.merry = {
name : "merry",
age : 18
}
}]);
app.directive('stuInfo',function(){
return {
restrict : 'E',
// = 号表示继承父作用域变量,通过这种方式可以将controller中的scope中的属性Jhon merry传递给给info属性,然后可以这里理解: isoleStuInfo = info = $scope.jack
scope :{
isoleStuInfo : '=info'
},
template : '<div>stuName:`{{isoleStuInfo.name}}`</div><div>stuAge:`{{isoleStuInfo.age}}`</div>'
}
})
</script>
</body>
</html>

通过以上示例我们这样可以将字符串或者一个对象传入isolate scope中

1.8 transclude属性 表明自定义的指令是否可以被嵌入,配合ng-transclude指令使用

transclude是一个可选的参数。如果设置了,其值必须为true,它的默认值是false。我们可以将整个模板,包括其中的指令通过嵌入全部传入一个指令中。这样做可以将任意内 容和作用域传递给指令。transclude参数就是用来实现这个目的的,指令的内部可以访问外部 指令的作用域,并且模板也可以访问外部的作用域对象。 为了将作用域传递进去,scope参数的值必须通过{}或true设置成隔离作用域。如果没有设 置scope参数,那么指令内部的作用域将被设置为传入模板的作用域

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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body ng-app = 'myApp'>
<div ng-controller = 'stuInfoCtrl'>
<p>this is Jhon</p>
<stu-info ng-transclude>
<div>原来的内容jhon</div>
<p>`{{jhon.name}}`</p>
</stu-info>
<p>this is merry</p>
<stu-info ng-transclude>
<div>原来的内容merry</div>
<p>`{{merry.name}}`</p>
</stu-info>
</div>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('stuInfoCtrl',['$scope',function($scope){
$scope.jhon = {
name : "Jhon",
age : 17
}
$scope.merry = {
name : "merry",
age : 18
}
}]);
app.directive('stuInfo',function(){
return {
restrict : 'E',
// = 号表示继承父作用域变量,通过这种方式可以将scope中的属性传递给给info属性的方式
transclude : true ,
scope:{},
template : '<div>模板的内容</div>'
}
})
</script>
</body>
</html>

控制台最终的结果如下:

1
2
3
4
5
6
7
8
9
10
11
this is Jhon
模板的内容
原来的内容jhon
Jhon
this is merry
模板的内容
原来的内容merry
merry

NodeJsFoundation

发表于 2016-11-20 | 分类于 nodejs

##1 node.js基础

  • 是建立在Chrome的JavaScript运行时很容易构建快速,可扩展的网络应用程序的平台。 Node.js使用事件驱动,非阻塞I/O模型,使得它重量轻,效率高,完美的跨分布式设备运行数据密集型实时应用。
  • 传统的网络服务技术,是每个新增一个连接(请求)便生成一个新的线程,这个新的线程会占用系统内存,最终会占掉所有的可用内存。而 Node.js 仅仅只运行在一个单线程中,使用非 阻塞的异步 I/O 调用,所有连接都由该线程处理,在 libuv 的加分下,可以允许其支持数万并发连接(全部挂在该线程的事件循环中)。
1
Node.js = Runtime Environment + JavaScript Library

1.1 node.js的特性

  • Node.js库异步和事件驱动 - 所有API异步是非阻塞。 这意味着一个基于Node.js的服务器不会等待API返回数据。 服务器移动到下一个API后调用它,Node.js事件的一个通知机制有助于服务器,以获得从以API调用的响应。
  • 非常快 - 正在构建在谷歌Chrome的V8 JavaScript引擎,Node.js库代码执行是非常快的。
  • 单线程但高度可扩展 - Node.js使用事件循环单线程模型。事件机制有助于服务器在非阻塞的方式作出反应,并使得服务器的高可扩展性,而不是它创建线程限制来处理请求的传统服务器。 Node.js使用单线程的程序和同样的程序处理比传统的服务器要大的多,比如:比Apache HTTP服务器请求服务的数量大得多。
  • 无缓冲 - Node.js的应用从来没有缓冲任何数据。这些应用程序只需输出块中的数据。
  • 许可证 - Node.js是在MIT许可下发布的。

1.2 node.js使用

  • 引入 required 模块:我们可以使用 require 指令来载入 Node.js 模块。

    这个是Node.js自带的http模块,然后将其赋值给http变量

1
var http = require("http");
  • 创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。以下代码可以建立一个正常工作的HTTP服务器;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var http = require('http');
//http模块提供的函数:createSever,该函数会返回一个对象,这个对象有一个listen方法,listen方法有一个数值参数,指定 这个HTTP服务器监听的端口号
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\n');
}).listen(8888);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
  • 接收请求与响应请求 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。

1.3 nodejs组成

  • 核心模块 由node环境提供,比如http fs,url , path等模块
  • 第三方模块,由社区,比如第三方提供,例如gulp browerSync moment等

##2 npm使用简介

1
2
3
4
5
6
7
8
9
10
11
12
13
$ npm -v 查看版本号
$ npm install <Module name> 安装Node.js的模块的语法格式,比如
$ npm install express (本地安装)这个是常用的web框架模块 express
$ npm install express -g (全局安装)
var express = require("express") ; //安装好之后,express 包就放在了工程目录下的 node_modules 目录中,因此在代码中只需要通过 require('express') 的方式就好,无需指定第三方包路径。
$ npm uninstall express //卸载Node.js模块
$ npm ls 命令可以查看本地安装的包
$ npm ls -g 命令可以查看全局安装的包
$ npm search express 可以用来搜索模块
$ npm init 可以创建模块,这个模块是你自己的模块,会创建一个package。json文件
$ npm publish 可以发布模块,发布以后就可以像其他模块一样使用npm来进行安装
比如 创建一个 $ npm init myMoudle 信息填写正确之后
$ npm install myModule 可以安装这个模块

Package.json 属性说明

  • name - 包名。
  • version - 包的版本号。
  • description - 包的描述。
  • homepage - 包的官网 url 。
  • author - 包的作者姓名。
  • contributors - 包的其他贡献者姓名。
  • dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。
  • repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。
  • main - main 字段是一个模块ID,它是一个指向你程序的主要项目。就是说,如果你包的名字叫 express,然后用户安装它,然后require(“express”)。
  • keywords - 关键字

NPM 常用命令

除了本章介绍的部分外,NPM还提供了很多功能,package.json里也有很多其它有用的字段。

NPM提供了很多命令,例如install和publish,使用npm help可查看所有命令。

  • NPM提供了很多命令,例如install和publish,使用npm help可查看所有命令。
  • 使用npm help可查看某条命令的详细帮助,例如npm help install。
  • 在package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试。
  • 使用npm update可以把当前目录下node_modules子目录里边的对应模块更新至最新版本。
  • 使用npm update -g可以把全局安装的对应命令行程序更新至最新版。
  • 使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人。
  • 使用npm unpublish @可以撤销发布自己发布过的某个版本代码。

3 Node.js REPL(Read Eval Print Loop) (交互式解释器)

  • 读取 - 读取用户输入,解析输入了Javascript 数据结构并存储在内存中。
  • 执行 - 执行输入的数据结构
  • 打印 - 输出结果
  • 循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。

Node 的交互式解释器可以很好的调试 Javascript 代码。并且可以直接调试node核心模块的代码;

比如下面的一些调试方法

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
$ node //可以启动node的终端
> url.parse('http://localhost:3000/a/b/c/d?name=Jhon',true)
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'localhost:3000',
port: '3000',
hostname: 'localhost',
hash: null,
search: '?name=Jhon',
query: { name: 'Jhon' },
pathname: '/a/b/c/d',
path: '/a/b/c/d?name=Jhon',
href: 'http://localhost:3000/a/b/c/d?name=Jhon' }
//使用简单表达式
> 3*6
18
//使用变量
> var x = 10
undefined //使用var生命的变量可以使用console.log打印出来
> console.log(x)
> console.log('hello there')
> x = 10
10 //没有使用var声明的变量在回车键之后会直接打印出来
//多行表达式
> var x = 0
undefined
> do {
... x++; //···符号是系统自动生成的,node会自动检测是否是连续的表达式
... console.log("x: " + x);
... } while ( x < 5 );
x: 1
x: 2
x: 3
x: 4
x: 5
undefined
//下划线(_) 变量可以直接获取表达式的运算结果
> var x =100
undefined //var声明的变量不会直接打印出来
> var y = _ // _ 变量可以获取表达式运算的结果
undefined //var声明的变量不会直接打印出来
> x++ //表达式运算的结果也会直接打印出来
100
> var y = _
undefined
> console.log(y) //打印运算结果
100
undefined
> ++x
102
> var y = _
undefined
> console.log(y)
102
undefined
> x+y
204
> var z = _
undefined
> console.log(z)
204
>

REPL 命令

  • ctrl + c - 退出当前终端。
  • ctrl + c 按下两次 - 退出 Node REPL。
  • ctrl + d - 退出 Node REPL.
  • 向上/向下 键 - 查看输入的历史命令
  • tab 键 - 列出当前命令
  • .help - 列出使用命令
  • .break - 退出多行表达式
  • .clear - 退出多行表达式
  • .save filename - 保存当前的 Node REPL 会话到指定文件
  • .load filename - 载入当前 Node REPL 会话的文件内容。

Transform

发表于 2016-11-19 | 分类于 css

Transform(3d):x轴向右是正方向,y轴向下是正方向,z轴垂直向外是正方向;注意transform:rotate(angle),可以使元素发生旋转,发生旋转之后的元素,其对应的 x y z的方向指向会发生变化,本文重点讲解;

在设置transition的前提下,transform变换才会有类似动画的效果

一:首先看一些有关3d的常用属性:

  • transform-origin:参数1 参数2

    设置对象的围绕的旋转中心,默认值是50% 50%

参数1 取值:百分比 基准是元素自身宽度,length 值,left center right 分别旋转中心是水平方向的左边界 居中 和右边界

参数2 取值:百分比 基准是元素自身高度,length 值,top center bottom 分别旋转中心是水平方向的左边界 居中 和右边界

如果第二个值没有设置默认是50%;

  • transform-style:flat | preserve-3d 默认是flat

    指定某元素的子元素是(看起来)位于三维空间内,还是在该元素所在的平面内被扁平化。只有在设置该属性值为preserve-3d的时候,才会有rotatex rotatey rotatez属性值,因为在2d里面只有rotate

当该属性值为「preserve-3d」时,元素将会创建局部堆叠上下文。
决定一个变换元素看起来是处在三维空间还是平面内,需要该元素的父元素上定义 <’ transform-style ‘> 属性。

  • perspective :none |length 默认是none

指定某元素距离浏览器窗口的垂直于浏览器窗口的距离,当length>0 的时候,会使得元素看起来比实际要大,length<0 的时候,会使得元素看起来比实际要小。

  • translate3d(x,y,z )三个参数不允许省略;

二 老司机带带我,不要走错路

transform: rotate(angle) translate(length | percentage)之间的关系。translate的百分比取值元素自身的宽(x)和高(y)来确定移动的距离。

1 明确浏览器的解析过程,从上到下 从左到右

2 明确rotate()会使坐标也跟着旋转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
img {
/*transform: translateX(1000px) translateY(500px) rotateZ(90deg);*/
transform: translateX(1000px) rotateZ(90deg) translateX(500px);
</style>
</head>
<body>
<img src="img/car.jpg" alt="" />
</body>
</html>
  • 代码执行过程1:

transform: translateX(1000px) translateY(500px) rotateZ(90deg);

对应的图片如下:执行过程是先向x轴正方向移动1000px,在向y轴正方向移动500px,然后图片围绕元素中心旋转90deg。

图xy1 : xy轴如下

执行完之后是

图xy2  :执行完rotateZ(90deg)

  • 代码执行2

    transform: translateX(1000px) rotateZ(90deg) translateX(500px);

最初状态是 图xy1 先向x轴正方向移动1000px 然后执行rotateZ(90deg),此时图片变换为 图xy2 所以这一步还是对应translateX(500px)来移动飞车。

注意:一般建议将旋转放在最后。不过还是眼看项目实际需求来

三 撸一段动画大家体验下:

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
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
img {
width: 200px;
}
@keyframes autoMove{
20%{
/*0~40%的时候的变换过程,初始默认x向右 y向下 z垂直向外*/
transform:translatex(1000px)
}
25%{
/*40%~50%的时候的变换过程*/
transform: translatex(1000px) rotatez(90deg);
}
50%{
/*50%~90%时候的变换过程*/
transform: translatex(1000px) translatey(500px) rotatez(90deg) ;
}
55%{
/*注意每次的变化都是在上一次的基础上进行变化*/
transform:translatex(1000px) translatey(500px) rotatez(180deg);
}
75% {
transform:translatex(0px) translatey(500px) rotate(180deg);
}
80% {
transform: translatex(0px) translatey(500px) rotate(270deg);
}
95% {
transform: translatex(0px) translatey(0px) rotate(270deg);
}
100%{
transform:translatex(0px) translatey(0px) rotate(360deg);
}
}
.autoMove{
animation:autoMove 5s linear ;
}
/*注意,每次动画都要保持上一步动画的结果,才能继续进行动画,如果不保持上一步动画的结果,那么会导致动画回归到原来的值*/
</style>
</head>
<body>
<img src="img/car.jpg" alt="" class="autoMove"/>
</body>
</html>

1 建议将每个阶段的动画注释掉,看下效果。

2 旋转的效果都是放在了最后,避免混乱。

gif动画效果

Angular Js MVVM 双向数据绑定如何实现

发表于 2016-11-17 | 分类于 javascript

1 我们先来看一个简单的双向数据绑定的demo

1.1点击按钮,数据的变化会实现在页面上显示出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body ng-app = "myApp">
<div ng-controller = 'myCtrl' >
<p ng-bind = 'count'></p>
<sapn ng-click =' increase() ' >icrease</sapn>
</div>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myCtrl',['$scope',function($scope){
$scope.count = 1 ;
$scope.increase = function(){
$scope.count++;
}
}])
</script>
</body>

1.2 angular底层是如何实现这种数据的双向绑定的呢?(参阅angular沉思录)

铺垫一点基础知识

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<button ng-click = 'inc1' id = 'btn'>increase</button>
</body>
<script>
var ret = document.querySelector('#btn').getAttribute('ng-click');
console.log(ret);//inc1
console.log(typeof ret);//string
console.log(window[ret]);//function inc1(){}函数
window[ret]();//inc1被执行了
function inc1 (){ //这个相当于给window对象添加一个属性,属性名是 inc1
counter++ ;
console.log('inc1倍执行了');
}
</script>
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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>two-way binding</title>
</head>
<body onload="init()">
<button ng-click="inc">
increase 1
</button>
<button ng-click="inc2">
increase 2
</button>
<span style="color:red" ng-bind="counter"></span>
<span style="color:blue" ng-bind="counter"></span>
<span style="color:green" ng-bind="counter"></span>
<script type="text/javascript">
/* 数据模型区开始 */
var counter = 0;
function inc() {
console.log("1");
counter++;
}
function inc2() {
console.log("2");
counter+=2;
}
/* 数据模型区结束 */
/* 绑定关系区开始 */
function init() {
bind();
}
function bind() {
var list = document.querySelectorAll("[ng-click]");
for (var i=0; i<list.length; i++) {
list[i].onclick = (function(index) {
return function() {
window[ list[index].getAttribute("ng-click") ]();//inc函数会执行
apply();
};
})(i);
}
}
function apply() {
var list = document.querySelectorAll("[ng-bind='counter']");
for (var i=0; i<list.length; i++) {
list[i].innerHTML = counter;
}
}
/* 绑定关系区结束 */
</script>
</body>
</html>

2 angular中的\$apply \$digest

首先我们来看下它们的作用,当我们在angularjs之外的上下文改变了model的时候,如何让angular进行页面的刷新呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body ng-app="test">
<div ng-controller="CounterCtrl">
<button myclick>increase</button>
<span ng-bind="counter"></span>
</div>
</body>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module("test", []);
app.directive("myclick", function() {
return function (scope, element, attr) {
element.on("click", function() {
scope.counter++;
console.log(scope.counter);
});
};
});
app.controller("CounterCtrl", function($scope) {
$scope.counter = 0;
});
</script>

这个时候我们是通过javascript处理函数改变了scope的counter值,此时会发现view视图上并不会跟随变化,但是控制打印出来的却是变化了的值。这是因为

  • angularjs只负责发生在angularjs上下文中的对于models 的更改会做出自动的回应(也就是$apply方法中对于model的更改orangular内置的其他服务)
  • 对于angular上下之外的其他地方修改的model,这个时候就需要手动调用$apply来触发一轮\$digest检测
  • build-in的一些 ng-event指令以及ng-model $timeout \$interval 等都会自动触发一次\$digest循环

$timeout(fn,delay,optional,pass) 第一个参数是执行函数,第二参数是延迟时间,第三个参数是是否进行脏值检测,默认是true,如果设置为false,则model数据的更新不会在视图上同步,pass是传递到执行函数的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body ng-app = 'myApp' >
<div ng-controller="myController">
<p>{{clock}}</p>
</div>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myController',['$scope','$timeout',function($scope,$timeout){
var updateClock = function() {
$scope.clock = new Date();
$timeout(function() {
updateClock();
}, 1000,false);//如果设置为false,发现不会model数据会更新,但是不会反应在view视图上
console.log($scope.clock);
};
updateClock();
}]);
</script>
</body>

$interval(fn,delay,count,optional,pass) 第一个参数是执行函数,第二个参数是延迟时间,第三个参数是fn执行的次数,第四个参数表示是否进行脏值检测,第五个蚕食表示传递的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body ng-app = 'myApp' >
<div ng-controller="myController">
<p>{{clock.now}}</p>
</div>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myController',['$scope','$interval',function($scope,$interval){
$scope.clock = {
now : new Date()
}
$interval(function(){
$scope.clock.now = new Date();
},1000,5);//5表示fn只会循环5次,如果不设置,则会无限循环,后面还可以设置false参数,表示不会进行脏检
}])
</script>
</body>

以上代码指令自定义可以变成以下三种方式

1
2
3
4
5
6
7
8
9
10
app.directive("myclick", function() {
return function (scope, element, attr) {
element.on("click", function() {
scope.counter++;
scope.$digest();
// scope.$apply(); //不推荐这种写法
console.log(scope.counter);
});
};
});

or

1
2
3
4
5
6
7
8
9
10
11
12
app.directive("myclick", function() {
return function (scope, element, attr) {
element.on("click", function() {
scope.counter++;
scope.$apply(function() {
scope.counter++;
});
console.log(scope.counter);
});
};
});

此时会发现view视图会随着model的改变实时更新了

再来个栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<body ng-app = 'myApp'>
<div ng-controller = 'myCtrl'>
<p ng-modle = 'name'>{{name}}</p>
<input type="text" ng-model = 'name'/>
<p>{{name}}</p>
<p>{{age}}</p>
</div>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myCtrl',['$scope',function($scope){
$scope.setInfo = function(){
setTimeout(function(){
$scope.$apply(function(){
$scope.name = 'Jhon';
$scope.age = 19;
})
},2000)
}
$scope.setInfo();
}])
//两秒后,会显示修改的scope内容
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
app.controller('myCtrl',['$scope',function($scope){
$scope.setInfo = function(){
setTimeout(function(){
$scope.name = 'Jhon';
$scope.age = 19 ;
$scope.$apply();
},2000);
}
$scope.setInfo();
console.log($scope);
}])

3 angular中的 $ watch

在上面的情况中,我们通过$apply \$digest函数的调用就可以将model模型上的数据变化实时反应在view层上,但是我们有没有思考为什么会model层的改变会实时显示在view层呢?这个时候就是watch的主要作用了当我们写下表达式,比如  的时候,angularjs在幕后为我们做了一件事情,

1
2
3
4
$scope.$watch('somevalue',function(){
console.log(arguments);//oldValue newValue scope
//这里实现更新view的逻辑,model层的数据变化实时更新到view层
})

也就是说,底层原理来讲是$watch回调函数的调用来执行的实时的数据更新,那么angularjs是怎么知道什么时候去调用这个回调函数呢?先抛出这个问题,看下这个demo,

  • 这种情况是scope模型上的数据改变了但是没有触发watch函数的情况,因为我们没有进行脏值检测$digest或者\$apply
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
<body ng-app = 'myApp'>
<div ng-controller = 'myCtrl'>
<p>{{age}}</p>
</div>
<script src="../libs/angular.js"></script>
<script>
var app = angular.module('myApp',[]);
app.controller('myCtrl',['$scope',function($scope){
$scope.age = 19 ;
$scope.change = function(){
setInterval(function(){
$scope.age++;
console.log("1");
console.log($scope.age);
},2000)
}
$scope.change();
$scope.$watch('age',function(){
console.log(arguments);//看下回调函数的参数
console.log("age变化触发了我的出现");
})
}])
</script>
</body>

控制台会循环输出 1 和  age的递增 ;

这个时候我们就需要思考了?通过什么方式触发$watch呢?修改change函数

1
2
3
4
5
6
7
$scope.change = function(){
setInterval(function(){
$scope.$apply(function(){
$scope.age++ ;
})
},2000)
}

这个时候我们会发现控制台会循环执行watch函数

AngularJsService

发表于 2016-11-17 | 分类于 javascript Angular

文墨(末)有彩蛋00哦

1 先来了解以下angular的依赖

Module依赖:在声明app模块时,需要给出依赖模块的列表。同时这些模块对应的JS需要在HTML中加以引入。在中可以直接使用依赖模块中声明的Service、Directive、Filter。

Service依赖:在声明Controller、Service、Directive、Filter的工厂方法中,把依赖的Service直接放到参数列表,Angular Injector会为你生成这些Service的实例。

1.1 Services 定义

AngularJS services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app.

AngularJS services are:

  • Lazily instantiated – AngularJS only instantiates a service when an application component depends on it.
  • Singletons – Each component dependent on a service gets a reference to the single instance generated by the service factory.

service通常用来进行不同的controller之间进行通信;

1.2 service声明方式 $provider 下面有五个API factory service value constant provider(这些都是provider的封装) 可以用来声明服务

1.2.1 最常见的方式:工厂方式,当someService作为依赖的时候,angular Injector会调用工厂方法,然后将返回值作为Service的实例传入依赖它的工厂方法

factory(name, fn)registers a service factory function that will be wrapped in a service provider object, whose $get property will contain the given factory function.

1
2
3
4
5
6
app.factory('someService', function(dependency1, ...){
return {
property1: value1,
property2: value2
}
});

走个小栗子

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
<body ng-app = 'myApp'>
<div ng-controller="myCtrl">
<input type="text" ng-model = 'info.name' placeholder="please input your name"/>
name:<p>`{{info.name}}`</p>
<input type="text" ng-model = 'info.age' placeholder="please input your age"/>
age:<p>`{{info.age}}`</p>
</div>
<script>
var myApp = angular.module('myApp',[]);
myApp.factory('myService',function(){
return {
name : "Jhon",
age : 18,
}
});
myApp.controller('myCtrl',["$scope","myService",function($scope,myService){
console.log(arguments);
$scope.info = myService ;
}]);
</script>
</body>

1.2.2 最直接的方式:构造函数 当someService作为依赖的时候,angular Injector会以new的方式调用该构造函数,然后将返回值作为Service的实例传入依赖它的工厂方法

service(name, Fn) registers a constructor function that will be wrapped in a service provider object, whose $get property will instantiate a new object using the given constructor function.

我们可以定义私有变量和共有变量

先来看下内部实现机制,angular Injector会以new的方式调用构造函数,然后将返回值传入依赖;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
function Service (){
this.public = {
name : "Jhon",
age :18
}
var private = {
name :"JiM",
age : 20
}
this.getPri = function(){
return private ;
}
}
var service = new Service();
console.log(service);
console.log(service.getPri());
</script>
1
2
3
4
app.service('someService', someService(dependency1, ...){
this.property1 = value1;
this.property2 = value2;
});
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
<body ng-app = 'myApp'>
<div ng-controller="myCtrl">
<input type="text" ng-model = 'info.name' placeholder="please input your name"/>
public name:<p>`{{info.name}}`</p>
<input type="text" ng-model = 'info.age' placeholder="please input your age"/>
public age:<p>`{{info.age}}`</p>
private name : <p>`{{infoPri.name}}`</p>
private name : <p>`{{infoPri.age}}`</p>
</div>
<script>
var myApp = angular.module('myApp',[]);
myApp.service('myService',function(){
this.public = {
name : "Jhon",
age :18
}
var private = {
name :"JiM",
age : 20
}
this.getPri = function(){
return private ;
}
});
myApp.controller('myCtrl',["$scope","myService",function($scope,myService){
console.log(arguments);
$scope.info = myService.public ;
$scope.infoPri = myService.getPri();
}]);
</script>
</body>

1.2.3 最简单的方式

value(name, value);

Register a value service with the $injector, such as a string, a number, an array, an object or a function. This is short for registering a service where its provider’s $get property is a factory function that takes no arguments and returns the value service. That also means it is not possible to inject other services into a value service.

Value services are similar to constant services, except that they cannot be injected into a module configuration function (see angular.Module) but they can be overridden by an AngularJS decorator.

constant(name, value);

Register a constant service with the $injector, such as a string, a number, an array, an object or a function. Like the value, it is not possible to inject other services into a constant.

But unlike value, a constant can be injected into a module configuration function (see angular.Module) and it cannot be overridden by an AngularJS decorator.

  • 两者的相同之处就是不能依赖其他的service,
  • 两者的不同之处就是value不能注册进其他模块,但是constant可以被注册进其他模块
  • 两者的不同之处还有就是value可以被decorator重写,但是constant不能被重写,constant常量的意思
1
2
3
app.value('someService', { property1: value1, property2: value2});
app.constant('anotherService', 'I am a simple string');

decorator(name, decorator);

Register a decorator function with the $injector. A decorator function intercepts the creation of a service, allowing it to override or modify the behavior of the service. The return value of the decorator function may be the original service, or a new service that replaces (or wraps and delegates to) the original service.

You can find out more about using decorators in the decorators guide.

get and set

发表于 2016-11-13 | 分类于 javascript

1 设置对象的属性,Object.definedProperty(obj.prop,descriptor)

1
2
3
4
5
6
7
8
//第一种方式
var obj= {};
Object.defineProperty(obj,"name",{
configurable:true,
enumerable : false,
value:"Jhon",
writable:true,
});
1
2
3
4
5
6
7
8
9
10
11
12
//第二种方式
var obj= {};
Object.defineProperty(obj,"name",{
configurable:true,
enumerable : false,
get : function(){
return "JiM";
}
set:function(){
}
});

2 一个属性的descriptor可能由以下组成 value writable configurable emuerable get set , descriptor是一个属性的详细信息描述的对象;

1
2
3
4
5
6
7
//通过键值对的方式直接设置对象的属性
const obj = {
foo:'bar',
};
var descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);//foo属性的descriptor对象的详细信息
console.log(obj);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//通过get set方法可以直接给对象设置属性以及设置属性值,大致了解下get和set的作用,以及对obj对象的属性改变
const obj = {
get foo() {
return 'bar';
},
get foo1() {
return 'bar1';
},
get foo2(){
return 'bar2'
}
};
var descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
console.log(obj);
console.log(obj.foo);//bar
console.log(obj.foo1);//bar1
console.log(obj.foo2);//bar2
obj.foo = 'bar4';//不会修改foo属性的值
console.log(obj.foo);//bar

3 set方法可以用来设置属性的值,get可以用来获取属性的值,来个栗子感受下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var test = {
_Name : "Lilei",
_Age : 20,
//_Name的只读
get name() {return this._Name;}, //通过
//_Age的读写
set age(age) {this._Age = age;},
get age() {return this._Age;}
}
console.log(test);//可以查看obj对象的所有属性,加深理解
var descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);//查看obj对象的所有属性的descriptor对象
//------------------------------------------------
console.log(test.name + " " + test.age);//Lilei 20
test.name = 'Lily';
test.age = 18;
console.log(test.name + " " + test.age);//Lilei 18
console.log(test._Name + " " + test._Age);//Lilei 18 _Name 只读,只写了_Age属性

transition transform 效果进阶1 body如何渐变色填充

发表于 2016-11-12 | 分类于 css

transition transform 效果进阶1 body如何渐变色填充

一 transition的拆分写

  • 明确其拥有的四个属性值

    transition-property 发生渐变效果的属性

transition-duration 完成过渡效果的时间

transition- timing-function 完成过渡效果的动画效果 linear ease ease-in ease-out

step-start= step(1 ,start)

step-end=step(1,end)

steps( n1,n2),n1代表完成的步数,n2代表start或者end ,指定每一步的值发生变化的时间点。第二个参数是可选的,默认值为end。

transition-deplay 开始进行过渡效果的延迟

  • transition 属性连写

transition : all 2s ease-in 1s

all 代表所有的属性都会有过渡效果,只要设置了,2s代表一个过渡效果的时间,ease-in 代表过渡的方式,1s代表延迟

二 transform属性(2d)(x 正方向水平向右,y正方向垂直向下,z正方向在垂直于窗口向外)

  • translate(x,y ) 指定对象移动,基准是父盒子左上角,移动 x y z是代表距离左上角的距离translatex(length|percentage),translatey(number)指定x y的移动距离。如果第二个参数省略,那么默认为0 ;其中百分比的基准是以元素自身的宽高为基准,然后乘以百分比,得到移动的距离值。

    ​ transform:translate(50px,40px)代表向右和向下移动50px 40px;

  • scale(x,y) ,代表指定对象缩放比例,x,y分别对应x y轴的缩放。scalex(number) scaley(number),如果第二个参数省略默认和第一个参数相等。

  • rotate(angle) 输入角度值,代表元素2d的旋转角度 需要有个transition-origin属性。关于旋转的方向:遵循“左手定则”大拇指指向轴的正方向,四指的方向就是旋转的方向,也是角度值为正的方向;rotate(angle),默认以z轴为基准进行旋转,rotatex(angel),rotatey(angle),rotatez(angle) 以x和y轴为基准进行旋转(3D)。注意在3d里面才有rotatex(angel),rotatey(angle),rotatez(angle),在2d里面只有rotate(angle)
  • skew(x,y) 指定x y的扭曲距离。如果第二个参数省略,那么默认为0 ;skewx(number) skewy(number).

三 : 有关body的渐变色填充问题:

​ body默认是没有高度的,但是却可以直接给body设置背景颜色,这是为什么呢?好多人会问,不是应该元素有了宽高才能有背景色吗?

这里明确一点,body设置背景色是浏览器自动配置的,如果直接给body设置背景色,默认全部填充整个文档;即使body的高度是默认的高度。

走个小demo理解下这个问题、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body {
background-color: blue;
/* background: linear-gradient(to bottom,rgba(0,0,255,0.1),rgba(0,0,255,0.5),rgb(0,0,255));*/
}
</style>
</head>
<body>
</body>
</html>

纯色填充

1
2
3
4
body {
background: linear-gradient(to
bottom,rgba(0,0,255,0.1),rgba(0,0,255,0.5),rgb(0,0,255));
}

渐变填充出问题了

给body一个高度:

​ height:100px ;

给个高度

我们会发现的问题是:纯色填充body没有问题,那么如何解决渐变填充body这种情况呢?

很简单,

1
2
3
html,body {
height :100% ;
}

解决问题

四 ,写个demo玩一下:

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
html,body{
height: 100%;
margin: 0;
}
body{
background: linear-gradient(to bottom,rgba(0,0,255,0.1),rgba(0,0,255,0.5),rgb(0,0,255));
box-sizing:border-box;
}
.fish {
width: 174px;
height: 126px;
background:url(img/fish.png) no-repeat;
/*border: 1px solid #000;*/
transition: all 2s linear;
}
body:hover .fish{
transform:translate(1000px,500px) rotate(45deg) scale(.5,.5);
}
/*背景图片默认左上角平铺,然后改变背景图片的位置即可*/
.animation {
animation: autoMove 1s steps(8) infinite;
}
/*动画关键字 */
@keyframes autoMove {
from {}
to {
background-position: 0 -1008px;
}
}
</style>
</head>
<body>
<div class="fish animation"></div>
</body>
</html>

AngularJsInitialization

发表于 2016-11-10 | 分类于 javascript

1 angularJs初始化应用模块有两种方式

1.1、绑定初始化,自动加载

通过绑定来进行angular的初始化,会把js代码侵入到html中。

ng-app是angular的一个指令,代表一个angular应用(也叫模块)。使用ng-app或ng-app=””来标记一个DOM结点,让框架会自动加载。也就是说,ng-app是可以带属性值的。如果没有ng-app指令将会报错;

自动初始化流程如下

ng-app 指令定义了 AngularJS 应用程序的 根元素

AngularJS 在 HTML DOMContentLoaded 事件后会自动引导(自动初始化)应用程序。如果找到 ng-app 指令 , AngularJS 载入指令中的模块,然后创建应用的注入器,并将 ng-app 作为应用的根进行编译。同时,启动应用的时候,会在其子元素范围内构成一个$scope;

应用的根可以是整个页面,或者页面的一小部分,如果是一小部分会更快编译和执行。

AngularJS initializes automatically upon DOMContentLoaded event or when the angular.js script is evaluated if at that time document.readyState is set to 'complete'. At this point AngularJS looks for the ngApp directive which designates your application root. If the ngApp directive is found then AngularJS will:

  • load the module associated with the directive.
  • create the application injector
  • compile the DOM treating the ngApp directive as the root of the compilation. This allows you to tell it to treat only a portion of the DOM as an AngularJS application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
通过控制体controller进行数据绑定
<body ng-app = 'Demo'>
<div ng-controller = 'DemoCtrl'>
`{{a}}+{{b}} = {{a+b}}`
</div>
<script>
//如果要对angular应用添加控制器,那么必须关联Demo到module模块,如果不关联那么则会提示没有
//The controller with the name 'xxx' is not registered.
angular.module('Demo',[]).controller('DemoCtrl',['$scope',function($scope){
$scope.a = 1 ;
$scope.b = 2 ;
}]);
</script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
通过run方法进行数据绑定,这个只能提供全局的变量
<body ng-app = 'Demo'>
<div >
`{{a}}+{{b}} = {{a+b}}`
</div>
<script>
var myapp = angular.module('Demo',[]);
console.log(myapp);
myapp.run(function($rootScope){
$rootScope.a = 1 ;
$rootScope.b = 2 ;
})
</script>
</body>
1
2
3
4
通过ng-init初始化数据
<div ng-app ng-init='name = "Jhon"'>
<div ng-bind="name"></div>
</div>

ng-app指令作用如下

There are a few things to keep in mind when using ngApp:

  • only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead.
  • AngularJS applications cannot be nested within each other.
  • Do not use a directive that uses transclusion on the same element as ngApp. This includes directives such as ngIf, ngIncludeand ngView. Doing this misplaces the app $rootElement and the app’s injector, causing animations to stop working and making the injector inaccessible from outside the app.

You can specify an AngularJS module to be used as the root module for the application. This module will be loaded into the $injectorwhen the application is bootstrapped. It should contain the application code needed or have dependencies on other modules that will contain the code. See angular.module for more information.

1.2 当同一个页面中包含多个app的时候(不能嵌套),这个时候angular就不能自动启动应用,需要我们用bootstrp手动启动应用

手动初始化一个angular应用模块,可以使用angular.bootstrap(),该方法可以初始化一个angularjs应用,注意该方法不会创建模块,我们在将模块作为参数传递之前必须先创建了一个模块或者已经先加载了一个模块

1
angular.bootstrap(element, [modules], [config]);

其中第一个参数element:是绑定ng-app的dom元素;
modules:绑定的模块名字
config:附加的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body >
<div ng-controller = 'DemoCtrl'>
` {{a}}+{{b}} = {{a+b}} `
</div>
<script>
angular.module('Demo',[]).controller('DemoCtrl',['$scope',function($scope){
$scope.a = 1 ;
$scope.b = 2 ;
}]);
//页面加载完毕之后在进行初始化模块
angular.element(document).ready(function(){
angular.bootstrap(document,['Demo']);
//angular.bootstrap(document.body,['Demo'])
//上面两行代码绑定同一个模块会报错,只能存在一个
})
</script>
</body>
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
<html>
<head>
<script src="angular.js"></script>
<script>
// 创建moudle1
var rootMoudle = angular.module('moudle1', []);
rootMoudle.controller("controller1",function($scope){$scope.name="aty"});
// 创建moudle2
var m2 = angular.module('moudle2', []);
m2.controller("controller2",function($scope){$scope.name="aty"});
// 页面加载完成后,再加载模块
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById("div1"),["moudle1"]);
angular.bootstrap(document.getElementById("div2"),["moudle2"]);
//绑定不同的模块是可以的
});
</script>
<head>
<body>
<div id="div1" ng-controller="controller1">div1:`{{name}}`</div>
<div id="div2" ng-controller="controller2">div2:`{{name}}`</div>
</body>
</html>

1.3 一个ng-app所在的标签就是一个angular应用,该标签下的所有子标签会被angular编译,不是其子标签的话不会被angular编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<body>
<div ng-app = 'app' ng-controller = 'myCtrl'>
<div>`{{name}}`</div>
<div>`{{age}}`</div>
</div>
<div>`{{age}}`</div>
<!--初始化ng-app,那么ng-app标签下面的子标签就是整个应用,其他的就不是angular应用,然后angular不会编译其余的标签
第二个age不会被angular编译,因此不会被显示19,只会显示{{age}}
-->
<script>
var app = angular.module('app',[]);
app.controller('myCtrl',['$rootScope','$scope',function($scope,$rootScope){
$rootScope.name = "Jhon";
$scope.age = 19 ;
}]);
</script>
</body>

1.4注意

  • ng-app和angular.bootstrap不能同时使用

  • ng-app只能出现一次,所以就只能出现一个angularjs应用,但是angular.bootstrap可以出现多次,但是这种做法是不推荐的

  • 二者初始化的一个应用的时候,所在元素的不能有ngIf ngView ngInclude指令

  • ng-app所在的标签的就是一个angular应用,该标签下面的所有的子标签都会被angular编译,不是该标签的子标签不会被angular编译

  • 初始化angular应用之后可以进行创建模块以及控制器、服务等其他操作

  • 初始化的angular应用里面的表达式会被编译,编译之后的表达式会按照angular的规定进行解析,如果没有ng-app指令或者bootstrap手动初始化angular应用,则表达式不会进行运算,将直接显示出来

  • HTML5 允许扩展的(自制的)属性,以 data- 开头。
    AngularJS 属性以 ng- 开头,但是您可以使用 data-ng- 来让网页对 HTML5 有效。

  • AngularJS 表达式 与 JavaScript 表达式

    类似于 JavaScript 表达式,AngularJS 表达式可以包含字母,操作符,变量。

    与 JavaScript 表达式不同,AngularJS 表达式可以写在 HTML 中。

    与 JavaScript 表达式不同,AngularJS 表达式不支持条件判断,循环及异常。

    与 JavaScript 表达式不同,AngularJS 表达式支持过滤器。

1…789…20
JiM-W

JiM-W

keep fighting!

195 日志
52 分类
90 标签
© 2017 JiM-W
由 Hexo 强力驱动
主题 - NexT.Pisces