一、面向对象-OOD
虽然js面向对象的编程思想已经老话常谈了,但了为了文章的完整性,我还是把它加了进来,尽量以不太一样的方式讲述(虽然也没什么卵不一样的)。
1、面向对象,首先得有类的概念,没有类造不出来对象,但是javascript中又没有类 只有函数的感念,把以大写字母命名的函数看成创建对象的构造函数,把函数名看成类,那么就可以new一个对象了
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
|
//1.1 无参的
function
People() {
}
var
p =
new
People();
//javascript为解释性语言,运行时编译,所以我们点什么属性,就会有什么属性了。
p.name =
'hannimei'
;
console.log(p.name);
//2.2 来个有参数的
function
Student(name, age) {
this
.name = name;
this
.age = age;
this
.say =
function
() {
return
saywhat();
}<br>
//私有函数<br> function saywhat(){<br> return this.name+':say what?';<br> }
return
this
;
}
var
s =
new
Student(
'lily'
, 18);
console.log(s.name);
console.log(s.say());
//2.3 来个factory
function
Factory(name,age) {
var
obj =
new
Object();
obj.name = name;
obj.age = age;
obj.say =
function
() {
return
obj.name+
':say what?'
;
}
return
obj;
}
var
o =
new
Factory(
'factory'
, 1);
console.log(o.say());
//2.4对象字面方式创建对象
var
ob = { Name:
"字面量"
, Age: 18 };
//当然也有字符串字面量、数组字面量这些
var
str =
'hello javascript!'
;
var
arr = [1, 2, 3, 4, 5];
|
2、那么有了类,面向对象同样不能少的特性就是继承;js中继承有各种方式的实现,通过函数原型链最常见不过了
天生自带技能乃是命,如果后来想修炼技能怎么办,直接点出来就好了嘛;如果不想修炼就想天生自带,那就得说下prototype了。
1
2
3
4
5
|
function
Teacher(schoolname) {
this
.schoolname = schoolname;
return
this
;
}
var
t =
new
Teacher(
'2b1中'
);
|
创建Teacher函数对象t时,t的__proto__指向了一个object,这个的指向其实就是函数的原型(为什么呢?听我慢慢往下道),如图:这个object又有两个属性,constructor定义了创建它的Teacher函数,__proto__继续向上指向Object,通过这种对象二叉树的结构,就标识了这个对象怎么来的和出生都自带什么技能。
那我们后台想自带技能就要通过增加t的__proto__指向的那个object默认技能了
从Teacher的监视图我们看到两个关键的属性,一个是它的函数原型prototype,测试得知这个东西和上图的__proto__指向同一个object,那么我们也就知道函数的另一个__proto__是指向它父级的Function的prototype,最终指向Object的prototype
经过上面的调理,我们终于明白了先天靠遗传,后天靠拼搏这句话的真谛;再试着回味一下这句话
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
|
//2.1 直接给prototype添加属性
function
Teacher(schoolname) {
this
.schoolname = schoolname;
return
this
;
}
Teacher.prototype.age = 18;
Teacher.prototype.jiangke =
function
() {
return
'老师开始讲课了'
;
}
var
t =
new
Teacher(
'2b1中'
);
console.log(t.age);
console.log(t.schoolname);
console.log(t.jiangke());
//2.2 通过prototype继承,prototype指向的是一个object,所以我们继承的话就指向父类new出来的对象就可以了
//这一句代码引发的长篇大论
function
People(name) {
this
.name = name;
this
.say =
function
() {
return
this
.name +
':say what?'
;
}
return
this
;
}
function
Student(name) {
this
.name = name;
}
Student.prototype =
new
People(Student.name);
var
s =
new
Student(
'啊弥陀丸'
);
console.log(s.say());
|
二、面向数据-DOP
1、初探
js面向数据编程这个概念是阿里什么论坛会上提出来的,简单的来说就是,大家懒得用js操作DOM元素了,通过直接对数据的赋值修改,然后替换到html模板中,最后直接调用innerHTML显;举个例子吧,虽然不够贴切 也不够完整,但话糙理不糙,它只是用来说明问题
这就是我们简陋的购物车,有两种水果和要购买的个数,通过+/-修改个数
1
2
3
4
|
<
div
id="gwcid">
<
p
>橘子:<
input
type="number" value="1" /><
input
type="button" value="+" onclick="changeEvent('orange');" /></
p
>
<
p
>苹果:<
input
type="number" value="1" /><
input
type="button" value="+" onclick="changeEvent('apple');" /></
p
>
</
div
>
|
传统的方式,我们会操作DOM,然后修改它的value值;但面向数据编程的时候需要的是,得现有一个json model,然后有一个html view,把操作后的属性值relace到view中,最后innerHTML大功告成。那么这种通用的编程方式的好处自然不言而喻,而且以现在浏览器渲染的速度,处理大数据时真是必备良品
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
var
fruits = { orange: 1, apple: 1 };<br>
//模板可以放入html中读取,此处为了方便
var
tpl =
'<p>橘子:<input type="number" value="<%orange%>" /><input type="button" value="+" onclick="changeEvent(\'orange\');"/></p><p>苹果:<input type="number" value="<%apple%>" /><input type="button" value="+" onclick="changeEvent(\'apple\');"/></p>'
;
function
changeEvent(name) {
//操作数据
fruits[name] += 1;
//替换值
var
result = tpl.SetValue(fruits);
//innerHTML
document.getElementById(
'gwcid'
).innerHTML = result;
}
String.prototype.SetValue =
function
(json) {
//regex replace
return
this
.replace(/<%\w+%>?/gi,
function
(matchs) {
var
str = json[matchs.replace(/<%|%>/g,
""
)];
return
str ==
"undefined"
?
""
: str;
});
}
|
2、开始及结束
经过上面的例子,相信js模板引擎啥的我们也就一并结束了吧,至少现在各种的模板引擎我也没太深入用,那些官方介绍的话也懒得贴出来了
大势所趋,现在后端许多核心的思想MVC、依赖注入、模块化等都被应用到了前段,而且连native的mvvm思想都搬了过来,说到这里,想必各位已经猜到接下来要说的东西--AngularJS,此处以文档学习为主,理论思想就懒得贴了。
2.1 Expression
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<h3>表达式</h3>
<input type=
"number"
ng-model=
"num1"
/>+<input type=
"number"
ng-model=
"num2"
/>
<p>结果为:{{num1+num2}}</p>
<hr />
<h3>字符串</h3>
<div ng-init=
"name='lily';age=18"
>
<p>姓名:{{name}},年龄 {{age}}</p>
</div>
<hr />
<h3>对象</h3>
<div ng-init=
"student={name:'lucy',age:16}"
>
<p>姓名:{{student.name}},年龄:{{student.age}}</p>
</div>
<hr />
<h3>数组</h3>
<div ng-init=
"nums=[1,2,3,4]"
>
<p>数组[1]:{{nums[1]}}</p>
<p>数组tostring:{{nums.toString()}}</p>
</div>
|
2.2 ng-
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
|
<!--ng-app:初始化AngularJS应用程序;ng-init:初始化应用程序数据。-->
<
div
ng-init="word='world'">
hello {{word}}
</
div
>
<!--ng-model:把元素值(比如输入域的值)绑定到应用程序-->
请输入:<
input
type="text" ng-model="input" />
你输入的是:{{input}}
<!--ng-show:验证不通过返回ture时显示-->
<
p
ng-show="true">可以看见</
p
>
<
p
ng-show="false">看不见</
p
>
<
p
ng-show="1=1">表达式成立可以看见</
p
>
<
form
action="/" method="post" ng-app="" name="form1">
email:<
input
type="email" name="address" ng-model="email" />
<
span
ng-show="form1.address.$error.email">请输入合法的邮箱</
span
>
<
ul
>
<
li
>字段内容是否合法:{{form1.address.$valid}}</
li
>
<
li
>表单是否有填写记录:{{form1.address.$dirty}}</
li
>
<
li
>字段内容是否非法:{{form1.address.$invalid}}</
li
>
<
li
>是否触屏点击:{{form1.address.$touched}}</
li
>
<
li
>是否没有填写记录:{{form1.address.$pristine}}</
li
>
</
ul
>
</
form
>
<!--ng-disabled:是否不可用-->
<
button
ng-disabled="true">点我!</
button
>
<!--ng-hide:是否可见-->
<
p
ng-hide="false">可以看见吧</
p
>
<!--ng-bind:绑定元素innerText的值-->
<
div
ng-init="quantity=3;cost=5">
价格:<
span
ng-bind="quantity*cost"></
span
>
</
div
>
<
div
ng-init="nums2=[10,20,30]">
<
p
ng-bind="nums2[1]"></
p
>
</
div
>
<!--ng-click:事件-->
<
div
ng-init="count=0;">
count:{{count}}
<
br
/><
button
ng-click="count=count+1">+1</
button
>
</
div
>
<!--ng-repeat:循环指令-->
<
div
ng-init="citys=[{name:'北京',val:1},{name:'上海',val:2},{name:'广州',val:3}]">
<
select
>
<
option
ng-repeat="x in citys" ng-bind="x.name" value="{{x.val}}"></
option
>
</
select
>
</
div
>
<!--ng-include:包含html内容-->
<
div
ng-include="'05service.html'"></
div
>
<!--自定义指令-->
<!--标签-->
<
runoob-directive
></
runoob-directive
>
<!--属性-->
<
div
runoob-directive></
div
>
<!--类名-->
<
div
class="runoob-directive"></
div
>
<
script
type="text/javascript">
var app = angular.module("myApp", []);
app.directive("runoobDirective", function () {
return {
//restrict: "E", E只限元素调用,A只限属性调用,C只限类名调用,M只限注释调用
//replace: true,当为M为注释时,可见为true
template: "<
h1
>自定义指令!</
h1
>"
};
});
</
script
>
|
2.3 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
|
<!--ng-controller 指令定义了应用程序控制器;在controller中给$scope添加属性,view中就可以传递过去使用了-->
<
div
ng-app="myApp">
<
div
ng-controller="ctrl">
{{name}}<
br
/>
{{say();}}<
br
/>
{{$root.genname}}
</
div
>
<
div
ng-controller="ctrl1">
{{$root.genname}}
</
div
>
</
div
>
<
div
id="div2" ng-app="myApp2" ng-controller="ctrl2">
{{name}}
</
div
>
<
script
type="text/javascript">
var app = angular.module('myApp', []); //'[]'用来创建依赖,没有的话 表示继续用之前创建的
app.controller('ctrl', function ($scope) {
$scope.name = 'scope';
$scope.say = function () { return 'hello,sister' };
});
//rootScope 根作用域,作用在整个app中,可以在各个controller中使用
app.controller('ctrl1', function ($scope, $rootScope) {
$rootScope.genname = '根作用域';
})
var app2 = angular.module('myApp2', []);
app2.controller('ctrl2', function ($scope) {
$scope.name = '另一个作用域了';
})
//手动启动第二个app,记清作用域哦
angular.bootstrap(document.getElementById('div2'), ['myApp2'])
</
script
>
|
2.4 Filter
1
2
3
4
5
6
7
8
9
10
11
12
|
<!--currency 格式化数字为货币格式。
filter 从数组项中选择一个子集。
lowercase 格式化字符串为小写。
orderBy 根据某个表达式排列数组。
uppercase 格式化字符串为大写。-->
<
div
ng-app="" ng-init="name='lily';citys=[{name:'北京',val:1},{name:'上海',val:2},{name:'广州',val:3}]">
{{name|uppercase}}
<!--表达式中添加-->
<
ul
>
<
li
ng-repeat="c in citys|filter:inp|orderBy: 'val'">{{c.name}}</
li
>
<!--指令中过滤-->
</
ul
>
<
input
type="text" ng-model="inp">
<!--输入过滤li-->
</
div
>
|
2.5 Service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<
div
ng-app="myApp" ng-controller="ctrl">
当前url:{{currenturl}}<
br
/>
get请求json数据:{{jsondata}}
自定义服务:{{myservice}}
</
div
>
<
script
type="text/javascript">
//自定义服务
angular.module('myApp', []).service('myservice', function () {
this.toStartUpper = function (str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
};
});
angular.module('myApp').controller('ctrl', function ($scope, $timeout, $location, $http, myservice) {
$scope.currenturl = $location.absUrl(); // $location 当前页面的 URL 地址
$timeout(function () { //$timeout等同于window.setTimeout;$interval等同于window.setInterval
console.log('timeout 执行了');
}, 2000);<
br
> //http请求 XMLHttpRequest
$http.get('json.txt').success(function (response) { $scope.jsondata = response; });
$scope.myservice = myservice.toStartUpper('service');
});
</
script
>
|
2.6 api
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<
div
ng-app="myapp" ng-controller="ctrl">
是否是字符串:{{isstr}}<
br
/>
是否是数字:{{isnum}}<
br
/>
转为大写是:{{strtoupper}}<
br
/>
</
div
>
<
script
type="text/javascript">
angular.module('myapp', []).controller('ctrl', function ($scope) {
$scope.str = 'sdfsdf';
$scope.isstr = angular.isString($scope.str);
$scope.strtoupper = angular.uppercase($scope.str);
$scope.isnum = angular.isNumber($scope.str);
});
</
script
>
|
2.7 animate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<!--ngAnimate 模型可以添加或移除 class 。
ngAnimate 模型并不能使 HTML 元素产生动画,但是 ngAnimate 会监测事件,类似隐藏显示 HTML 元素 ,如果事件发生 ngAnimate 就会使用预定义的 class 来设置 HTML 元素的动画。-->
<
input
type="checkbox" ng-model="mycheck">点我隐藏div
<!--添加/移除 class 的指令:
ng-show
ng-hide
ng-class
ng-view
ng-include
ng-repeat
ng-if
ng-switch
ng-show 和 ng-hide 指令用于添加或移除 ng-hide class 的值
其他指令会在进入 DOM 会添加 ng-enter 类,移除 DOM 会添加 ng-leave 属性
当 HTML 元素位置改变时,ng-repeat 指令同样可以添加 ng-move 类
-->
<
div
ng-hide="mycheck"></
div
>
<
script
type="text/javascript">
var app = angular.module('myApp', ['ngAnimate']);
</
script
>
|
2.8 DI
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
|
var app = angular.module('myapp', []);
//注入value
app.value('defaultval', 0);
//factory 注入service
app.factory('sumService', function () {
var factory = {};
factory.sum = function (a, b) {
return a + b
}
return factory;
});
//自定义computeServer服务
app.service('computeServer', function (sumService) {
this.sum = function (a, b) {
return sumService.sum(a, b);
};
});
//provider
app.config(function ($provider) {
$provider.provider('sumService', function () {
this.$get = function () {
var factory = {};
factory.sum = function (a, b) {
return a + b;
}
return factory;
};
});
});
//constant 常量配置
app.constant('save', 'false');
//注入的value
app.controller('ctrl', function ($scope, defaultval) {
$scope.defaultval = defaultval;
});
|
2.9 route
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">
<
ul
>
<
li
><
a
href="#/">首页</
a
></
li
>
<
li
><
a
href="#/product">产品</
a
></
li
>
<
li
><
a
href="#/about">关于</
a
></
li
>
</
ul
>
<
div
ng-view></
div
>
<
script
type="text/javascript">
//添加route依赖
angular.module('myapp', ['ngRoute'])
///$routeProvider.when(url, {
// template: string, 在 ng-view 中插入简单的 HTML 内容
// templateUrl: string, templateUrl 插入html模板文件
// controller: string, function 或 array, function、string或数组类型,在当前模板上执行的controller函数,生成新的scope。
// controllerAs: string, string类型,为controller指定别名。
//redirectTo: string, function, 重定向地址
// resolve: object<
key
, function> 指定当前controller所依赖的其他模块
// });
.config(['$routeProvider', function ($routeProvider) { //$routeProvider 用来定义路由规则
$routeProvider.when('/', { template: '这是首页' }) //$routeProvider.when 函数的第一个参数是 URL 或者 URL 正则规则,第二个参数为路由配置对象。
.when('/product', { template: '这是产品' })
.when('/about', { template: '这是关于我们' })
.otherwise({ redirectTo: '/' });
}]);
</
script
>
</
body
>
|
三、面向H5
html5给力之处,无非是javascript大量的api;像以前想要修改url参数不跳转做标识用,只能用#,有了pushStata 呵呵呵;更或者做webim轮询服务器,现在windows server12+websocket直接搞起(还是用signalr实在点,装逼也没人信);当然 不论是本地数据库还是websocket更或者是强大的canvas api等等等太多,其实都不如querySelector、querySelectorAll这类的api来的实在(用惯了jquery选择器的可能都这么想)
那么问题来了,既想写一套代码,又想用h5新api的写法,跟着潮流 不然就out了;那么就需要兼容IE8及下,为他们实现h5这些个常用的api就好了撒
思想已经出来了,但雏形还未跟上,虽然很简单,但是我还是厚着脸皮写出来了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<
input
type="text" id="inputid" name="name" value="none" />
<
script
type="text/javascript">
if (!window.localStorage) {
document.write('<
script
src="xxx.js"><\/script>');
//document.write('<
script
src="jquery-1.9.1.js"><\/script>');
//(function (d) {
// d.query = function (selector) {
// return $(selector)[0];
// }
// Element.prototype.addEvent = function (types, fn) {
// return $(this).bind(types, fn);
// }
//})(document);
}
window.onload = function () {
var obj = document.query('#inputid');
console.log(obj.value);
obj.addEvent('change', function () {
console.log(this.value);
})
};
</
script
>
|