# Node.js 是什么?

node.js 是一个运行 JS 的平台。原来的 JS 脚本只能在浏览器中执行,要想让它脱离出来可以在任意地方都能够执行 JS。JS 当后端语言来使用,必须要安装 Nodejs。安装了 Nodejs 就相当于是安装了 V8 引擎(谷歌中的 JS 解析器)。总的来说:

  1. Nodejs 是一个运行 JS 的平台,不是一门语言,也不是 JS 框架或 js 库,不能像 jquery 那样可以引入到网页,增加新功能。
  2. Nodejs 主要是用于开发网站,即网络应用和本地应用、构建工具等,可以做 JS 不能做的事情,比如读取文件,连接数据,网络服务等。类似于 PHP。
  3. 安装 Nodejs 环境的目的:是想要让 JS 能脱离浏览器环境也可以单独执行。相当于是安装了一个解析 JS 的平台。如果安装了该环境,就可以在电脑的任意文件夹中执行 JS 代码。
  4. Nodejs 是与浏览器无关的。它能执行的 JS 只能是 ecmascript,不能执行 DOM,BOM 的方法和属性。

# node.js 可以做什么?

  1. 可以读写本地文件 。
  2. 完成前端构建化工作:压缩、打包(webpack)。
  3. 是服务器语言,地位等同于 java,PHP,.net,意味着可以直接使用 JS 来做一个动态网站(可以连接数据库)(前端也可以做后端了)。
  4. 可以开发软件、APP,比如:VScode。

# 使用 Nodejs 的两种方式

  1. 交互模式(浏览器的控制台)。

    1. 退出:ctrl+C 退出。
    2. 进入:在命令行中输入 node 回车即可。
  2. 直接执行一个本地 JS 文件(显示了目录才算)。

    首先在本地写一个 JS 文件,然后通过命令行定位到当前目录,输入 node js 文件名.js 回车执行。

# 学 Nodejs 的目的

  1. 了解这门后端语言。
  2. 为前端构建化做准备。
  3. 为 Vue 的豪华版做准备。

# JS 的模块化

如何解决 JS 模块化产生的命名冲突和变量污染问题:

  1. 使用变量前缀

    比如两个相同名字的同学如何区分。var moduleA_a=1; var moduleB_a=1;
    问题:仍然存在大量全局变量或函数(治标不治本)。

  2. 命名空间(使用一个对象来装一个人写的代码)。

    将变量和属性全部放在对象中,再通过对象来访问模块属性和方法。
    问题

    1. 当代码越来越大时,容易出现对象嵌套对象的情况。会导致访问路径过长
    2. 所有属性和方法都会暴露,其他模块可以轻松改变该模块对象。
  3. IIFE(立即执行函数表达式)Immediately Invoked Function Expression。
    好处

    1. 可创建私有作用域(变量,函数)避免命名冲突。
    2. 能实现模块的开发,是较为完美推荐的方式。

# todolist 实例

# 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
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

<!DOCTYPE html>
<html lang="zh-CN">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/style.css">
<!-- 乞丐版的vue,所以像JQ那样导入到当前页面中即可 -->
<script src="vue.v2.6.12.js"></script>
</head>

<body>
<!-- 注意,不能将vue控制视图的元素定位到body或HTML,会报错
添加v-cloak指令,等数据准备好后再显示视图
-->
<div id="app" v-cloak>
<header>
<h2>
<span>任务计划表</span>
<span class="skin">
<!-- 皮肤切换样式,点击时改变皮肤数据,并添加对应的高亮样式 -->
<a href="#" :class="{cur:config.skin==0}" @click="config.skin=0"></a>
<a href="#" :class="{cur:config.skin==1}" @click="config.skin=1"></a>
</span>
<!-- 皮肤样式 如果是红色,禁用样式-->
<link rel="stylesheet" :disabled="config.skin==0" href="css/skin_green.css">
</h2>
</header>
<section class="content">
<h4 class="tit">添加任务:</h4>
<input type="text" class="newtodo" v-model="ipt" @keyup.enter="add" placeholder="回车即可添加任务">
<div class="tabBar">
<div class="taskStatus">
<span class="notDone" v-show="notDoneLen>0">{{notDoneLen}}个任务未完成</span>
</div>
<div class="tabTit">
<a href="#" v-for="(item,i) in config.tabTit" @click="changeTab(i)"
:class="{cur:index==i}">{{item}}</a>
</div>
</div>
<h4 class="tit">任务列表:</h4>
<!-- <div class="tabPanel"> 启用列表过渡 -->
<transition-group tag="div" class="tabPanel">
<!-- @tofather是接收来自子组件派发过来的数据,该数据即为点击的事项的索引 -->
<tab-panel :list="tdlist" v-show='index==0' @tofather="delItem" key="0"></tab-panel>
<tab-panel :list="ndList" v-show='index==1' @tofather="delItem" key="1"></tab-panel>
<tab-panel :list="hdList" v-show='index==2' @tofather="delItem" key="2"></tab-panel>
</transition-group>
<!-- </div> -->
</section>

</div>


<script>
let dataHandler = {
get() {
return JSON.parse(localStorage.getItem("todolist")) || [];
},
set(d) {
localStorage.setItem("todolist", JSON.stringify(d));
}
};
let Handler = {
get() {
return JSON.parse(localStorage.getItem("skin")) || [];
},
set(d) {
localStorage.setItem("skin", JSON.stringify(d));
}
};
//面板组件,所有的组件视图都一样,只有数据不一样,所以只需要传递数据即可
Vue.component("tab-panel", {
props: ['list', 'index'],
data() {
return {
msg: "Silence is gold!"
};
},
methods: {
del(i) {
// console.log(1)
// 将当前点击的事项的索引传递给父级进行删除
this.$emit('tofather', i);
}
},
template: `
<ul class="todolist" >
<template v-if="list.length>0">
<li v-for="item,ii in list" :class="{completed:item.checked}">
<label>
<input type="checkbox" v-model="item.checked">
<span>{{item.name}}</span>
<a href="#" @click="del(ii)">x</a>
</label>
</li>
</template>
<li class="nolist" v-else>
{{msg}}
</li>
</ul>
`
});
// vue的实例(根实例)
let vm = new Vue({
el: "#app",
data: {
// 输入框
ipt: '',
// 所有任务
tdlist: dataHandler.get(),
// 未完成任务
// ndList:[],
// 已完成任务
// hdList:[],
// 标记当前要显示的面板
index: 0,
//网页基本配置数据
config: {
// tab标题
tabTit: ['所有任务', '未完成的任务', '完成的任务'],
// 皮肤,0表示红色,1表示绿色
skin: Handler.get()
}
},
methods: {
add() {
//验证: 去除空格后假设还是空字符串,则什么也不做
if (this.ipt.replace(/\s+/, '') == '') {
return false;
}
this.tdlist.push({
name: this.ipt,
checked: false
});
this.ipt = "";
},
// 未完成任务
changeTab(i) {
this.index = i;
},
// 通过子集传递数据过来删除数据
delItem(i) {
// 删除下标所对应的数据
this.tdlist.splice(i, 1);
}

},
watch: {
//通过监听tdlist拆解得到未完成事项和已完成事项
tdlist: {
handler() {
dataHandler.set(this.tdlist);
},
deep: true
},
// 设置皮肤
config: {
handler() {
Handler.set(this.config.skin)
},
deep: true
}
},
computed: {
// 统计未完成
notDoneLen() {
return this.tdlist.filter(item => !item.checked).length;
},
// 未完成
ndList(){
return this.tdlist.filter(item => !item.checked);
},
// 已完成
hdList(){
return this.tdlist.filter(item => item.checked);
}
},
});
</script>
</body>

</html>

# style.css

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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208


/*公共样式*/
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
body{
background-color: #fafafa
}
header{
height: 60px;
line-height: 60px;
background-color: #DB4C3F;
}
header h2{
width: 900px;
color: #fff;
font-weight: 400;
margin: 0 auto;
}
/*等所有的数据加载完毕再显示*/
[v-cloak]{
display: none;
}
/*右上角皮肤选择按钮*/
.skin{
float: right;

}
.skin a{
display: inline-block;
width: 25px;
height: 25px;
/*border-radius: 50%;*/
border: 2px solid #fff;
vertical-align: -3px;
position: relative;
}
.skin a:first-child{
background-color: #DB4C3F;
}
.skin a:last-child{
background-color: #41b883;
}
.skin .cur:before{
content:" ";
background-color: #fff;
font-size:20px;
position: absolute;
top: 3px;
left: 3px;
line-height: 1;
width: 15px;
height: 15px;

}
/*内容区域*/
.content{
width: 900px;
margin: 0 auto;
}
.tit{
margin: 15px 0;
font-size: 22px;
font-weight: 400
}
.newtodo{
padding: 10px 15px;
border:1px solid #ddd;
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
width: 100%;
font-size: 24px;
}
:focus {
/*outline: 0;*/
outline-color: #DB4C3F
/*background-color: #FCF1F1*/
}
.tabBar{
margin: 15px 0;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 18px;
}
.notDone{
color: #DB4C3F
}
.tabTit a{
display: inline-block;

/*border: 1px solid transparent;*/
padding: 10px 20px;
text-decoration: none;
color: #000;
}
.tabTit a.cur{
background-color: #DB4C3F;
color: #fff;
/*border: 1px solid #DB4C3F;*/
border-radius: 5px;
}
.todolist li{
padding: 10px;
border-bottom: 1px solid #e6e6e6;
list-style: none;
}
.todolist li label{
display: block;
}
.todolist li input,.todolist li a{ display: inline-block; width: 45px; }
.todolist li input{
height: 25px;
vertical-align: -5px;}
.todolist li a{ float: right; display: none; font-size: 20px }
.todolist li:hover a{color: #af5b5e; display: block; }
.todolist li span{ font-size: 1.5em; }
.todolist li:last-child {
border-bottom: none;
}
.tabPanel{
position: relative;
}
/*解决列表过渡动画bug*/
.tabPanel ul{
width: 100%;
position: absolute;
background-color: #fff;
min-height: 100px;
}
/*事项完成时*/
.completed{color: #d9d9d9;text-decoration: line-through;}
/*暂无任务请添加*/
.nolist{
text-align: center;
line-height: 80px;
font-size: 20px;
color: #999;
}
/*过渡样式*/

.v-enter-active{
animation: shake 0.5s;
}
/*.v-leave-active{
animation: shake 1s;
}*/
/*动画关键帧*/
@keyframes tada {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}

10%,
20% {
-webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
}

30%,
50%,
70%,
90% {
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
}

40%,
60%,
80% {
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
}

to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}

@keyframes shake {
from,
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}

10%,
30%,
50%,
70%,
90% {
-webkit-transform: translate3d(-10px, 0, 0);
transform: translate3d(-10px, 0, 0);
}

20%,
40%,
60%,
80% {
-webkit-transform: translate3d(10px, 0, 0);
transform: translate3d(10px, 0, 0);
}
}

# skin_green.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

header{
background-color: #41b883;
}

:focus {
outline-color: #41b883
}

.notDone{
color: #41b883
}

.tabTit a.cur{
background-color: #41b883;
}

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

tz 微信支付

微信支付

tz 支付宝

支付宝