第一阶段学习目标是基于node.js express开发一个demo,学习一下从头开始搭建一个环境,完成一个demo的研发,并学习几种技术。
代码地址:https://github.com/wsxwang/bsdemo。
【HTML、JavaScript、CSS】
【node.js】
基础入门:http://www.cnblogs.com/binperson/p/5507235.html。
【express】
【jade模板】
https://segmentfault.com/a/1190000000357534。
http://www.jianshu.com/p/e2a9cd3b7e56。
【vue】
【Element UI】
http://element.eleme.io/#/zh-CN。
下载地址:http://nodejs.cn/download/
【Windows环境下的安装】
根据操作系统选择安装包(32位或64位),按默认选项一步步点击下一步,完成安装即可。
安装完成之后,打开命令行,输入node –version,输出版本号,我安装的8.4.0版本,形如:V8.4.0,即表示安装完毕。
【Ubuntu15.04环境下的安装】
系统自带的node.js版本过低,下载最新的源码包node-v8.4.0.tar.gz,解压(tar –zxvf node-v8.4.0.tar.gz)、安装(sudo ./configure &sudo make –j 4& sudo make install)。
npm是node.js自带的包管理工具,用于安装第三方包,以及部署工程。
npm在node.js中自带,无需安装。
npm的升级,使用命令:npm install npm -g,ubuntu环境下需要使用sudo。
npm版本查看,使用命令:npm –version,输出版本号。
npm安装,使用命令:npm install XXX -g,其中-g命令表示全局安装,否则表示本地安装,本地安装将只把XXX模块安装在当前目录。
安装模块时,npm会自动更新package.json以及package-lock.json,并把模块安装在node_modules目录下,若json文件不存在,package-lock.json会自动新建,但package.json文件需要提前建好。
具体参考:http://www.runoob.com/nodejs/nodejs-npm.html。
express是node.js的一个模块,在工程目录下,使用npm install express进行本地安装。
jade是模板渲染的一个引擎,适合于后端页面的渲染,使用命令npm install jade –global进行安装。
安装完成后,使用命令jade -P –O $JSON XXX.jade,可将XXX.jade模板编译为html文件,-P表示生成带缩进的html文件,-O后面跟作为参数传递的json信息。
vue适合用于前端交互环境下的html渲染及数据交互。
在线使用时,在html代码中加入以下代码即可。
<script src="//unpkg.com/vue/dist/vue.js"></script>
elementui可认为是一套页面模板,在线使用时,在html代码中加入以下代码即可。
<script src="//unpkg.com/element-ui@1.4.4/lib/index.js"></script>
开发工具选用WebStorm。
WebStorm可帮助初始化工程,避免使用npm命令行。
使用WebStorm新建一个express工程,如下图所示(如果环境安装正确,WebStorm会自动定位相关运行环境。
点击Create按钮之后,会在指定目录生成一个工程,目录结构如下图所示:
【bin】
bin目录下保存的www文件是执行入口。启动方式是:node ./www,或者在上一级目录下执行npm start,查看package.json文件,实质上二者是一回事。
【node_modules】
这个目录保存node.js的依赖模块。
WebStorm建立新工程时会下载。
【public】
存放静态文件,WebStorm默认建立images、javascripts、stylesheets,其中stylesheets目录下默认建立style.css文件。
【routes】
存放路由文件,WebStorm默认建立index.js和users.js两个文件。
【views】
存放视图目录。WebStorm默认使用jade模板引擎,默认建立error.jade、index.jade、layout.jade三个文件,其中error.jade、index.jade均扩展自layout.jade。
【app.js】
app.js是主入口文件
【package.json】
package.json用于定义模块的属性。
可以用npm init来初始化这个文件。
npm安装、卸载、更新包时,会更新这个文件中的依赖关系。
【package-lock.json】
记录整个 node_modules文件夹的树状结构。
参考这个文章:http://www.topjishu.com/11681.html。
建立src目录,在src目录下根据业务模块设置不同目录,将js文件、渲染模板、路由文件、html等等均放置于模块目录下。
修改app.js,加入以下代码
app.use('/src/', express.static(path.join(__dirname, 'src')));
将src目录纳入静态资源目录(挂载于/src/)。
【方法一、使用app实例注册】
var users = require('./routes/users'); var app = express(); app.use('/users', users);
【方法二、使用router注册】
适用于在页面中注册子页面的场景。
var router = express.Router(); var dbopr = require('../src/dbopr/dbopr'); router.use('/dbopr', dbopr);
入口页面设计为一个简单的超链接,每一个链接到不同的demo页面。复用默认的’/’路由(index.js),使用jade渲染模板(index.jade)。
【修改入口页面】
修改index.jade模板,改为以下内容:
extends layout block content h1= title p #{desc} p each page in pages li a(href=page['link']) #{page['text']}
修改index.js,改为以下内容:
var express = require('express'); var router = express.Router(); // 注册子页面路由 var htmldemo = require('../src/htmldemo/htmldemo'); router.use('/htmldemo', htmldemo); var dbopr = require('../src/dbopr/dbopr'); router.use('/dbopr', dbopr); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'bs demo', desc: 'demo入口,使用jade模板渲染,多个demo的入口', pages:[ {link: 'htmldemo', text:'html+vue', title:'在html网页中直接使用vue的demo'}, {link: 'dbopr', text:'数据库操作', title:'xxx demo'} ] }); }); module.exports = router;
这个demo是在express中直接使用html页面,并使用vue渲染,演示如何动态生成表格。使用vue做前端交互式渲染比较适合。
共两个文件:
htmldemo.js:路由文件。代码较为简单,直接发送html文件即可。
router.get('/', function(req, res, next) { res.sendfile(__dirname + '/htmldemo.html'); } );
htmldemo.html:页面文件,包含html页面、js脚本、css脚本。
<!DOCTYPE html> <html lang="en" xmlns=""> <head> <meta charset="UTF-8"> <title>html+vue</title> </head> <body> <!-- 以ID:tabledemo与vue实例绑定 --> <div id="tabledemo" class="div"> <h1 id="head" class="h" v-bind:title='headtitle'> {{headmessage}} </h1> <!-- 分两个部分:div-config和div-content,分别承载表格的配置和表格本身 --> <div id="div-config" class="div"> 列头 <input name="columnname" v-model="column" title="逗号分割"> <br> 行数 <input name="rowcount" v-model="rowcount"> <br> <button @click="filldata">重新生成</button> </div> <div id="div-content" class="div"> <!-- 表格使用自定义的vue组件autofill-table,将vue实例的columns和rows数据分别与heads和data属性绑定 --> <autofill-table id="autofill-table" v-bind:heads="columns" v-bind:celldatas="rows"></autofill-table> </div> </div> <!-- 使用script方式引入vue --> <script src='https://unpkg.com/vue@2.0.5/dist/vue.js'></script> <!--表格模板,用于autofill-table--> <script type="text/x-template" id="table-template"> <table> <thead> <tr> <th v-for="h in heads">{{h}}</th> </tr> </thead> <tbody> <tr v-for="r in celldatas"> <td v-for="cell in r">{{cell}}</td> </tr> </tbody> </table> </script> <!-- Vue --> <script> // 定义一个Vue组件,动态生成表格,使用表格模板table-template Vue.component('autofill-table',{ template:"#table-template", props: { celldatas: Array, //数据数据 heads: Array //列头数组 } }); var app = new Vue({ el: '#tabledemo', data: { headmessage: '表格demo,html网页嵌入vue脚本', headtitle:'可定制列头和行数,随机生成数据', column:'编号,数量', //列头 rowcount:10, //行数 columns:["编号", "数量"], //列头列表 rows:[] //行数据 }, methods:{ // 生成表格,变更数据columns和rows filldata: function () { this.columns = this.column.split(","); this.rows = new Array(this.rowcount); for(var i = 0; i < this.rowcount; i ++) { this.rows[i] = {}; for(var j = 0; j < this.columns.length; j ++) { this.rows[i][j] = i.toString() + "," + j.toString(); } } } } }) </script> <!-- css --> <style type="text/css"> #tabledemo h1{ text-align: center; color: lightseagreen; background-color: cornsilk; } #div-content table, th, td{ border: 1px solid black; } #div-content td{ border: dashed blue; } </style> </body> </html>
这个demo是在express中直接使用jade渲染页面。Jade更适合用做后台数据展示的渲染,因此在路由中直接指定参数,在jade中取得参数进行渲染。
共三个文件:
jadedemo.js:路由文件。将需要渲染的数据作为参数传递。
router.get('/', function(req, res, next) {
res.render(__dirname + "/jadedemo.jade",{
'pagetitle': '布局展示,jade渲染',
'items':['甲', '乙', '丙','丁']
});
}
);
jadedemo.jade:jade脚本,用于渲染html文件。
extends ../../views/layout
block content
h1#pagetitle= pagetitle
each i in items
li=i
link(rel='stylesheet', href='/src/jadedemo/jadedemo.css')
jadedemo.css:css脚本。
h1{
color: crimson;
font: "Nirmala UI";
}
li{
color: navy;
font: "Droid Sans"
}
这个demo是演示在html中通过vue绑定使用elementui控件,演示折叠面板和进度条控件。
共四个文件:
elementuidemo.js:路由文件。
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.sendfile(__dirname + '/elementuidemo.html');
}
);
module.exports = router;
elementuidemo.html:页面文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学习elementui的demo</title>
<!-- 使用script方式引入vue -->
<script src="//unpkg.com/vue/dist/vue.js"></script>
<!-- 使用script方式引入elementui -->
<script src="//unpkg.com/element-ui@1.4.4/lib/index.js"></script>
</head>
<body>
<div id="elementuidemo">
<h1>{{message}}</h1>
<el-row>
<el-col :span="12">
<div class="grid-content bg-purple">
<el-collapse v-model="chosenPanel" accordion v-on:change="OnChange">
<el-collapse-item title="进度条" name="1">
<div>进度条演示</div>
</el-collapse-item>
<el-collapse-item title="未实现" name="2">
<div>xxxx</div>
</el-collapse-item>
</el-collapse>
</div>
</el-col>
<el-col :span="12">
<div class="grid-content bg-purple-light">
<div id="progress-panel" v-if="chosenPanel==1">
<el-progress type="circle" :percentage="progress" v-bind:status="progressStatus"></el-progress>
<el-button id="start" @click="startProgress">{{startButtonText}}</el-button>
<el-button id="reset" @click="resetProgress">复位</el-button>
</div>
</div>
</el-col>
</el-row>
</div>
<!-- 引入vue脚本 -->
<script src="/src/elementuidemo/elementuidemo.vue"></script>
<!-- 引入css脚本 -->
<link rel="stylesheet" href="/src/elementuidemo/elementuidemo.css"></link>
</body>
</html>
elementuidemo.vue:vue脚本文件。
new Vue({
el:"#elementuidemo",
data:function(){
return {
message:'使用elementui的demo',
chosenPanel:'1',
progress:60,
progressStatus:'',
startButtonText:'启动',
intervalid:0,
};
},
methods:{
OnChange:function(activeNames) {
console.log(activeNames);
},
increseProgress:function(){
this.progress += parseInt(Math.random()*10+1);
this.progress %= 100;
},
startProgress:function(key){
if (this.startButtonText == '启动')
{
this.startButtonText="停止";
this.interval = window.setInterval(this.increseProgress, 1000);
}
else
{
this.startButtonText="启动";
window.clearInterval(this.interval);
}
},
resetProgress:function (key) {
if (this.startButtonText == '停止')
{
this.startButtonText="启动";
window.clearInterval(this.interval);
}
this.progress = 0;
}
},
});
elementuidemo.css:css脚本文件。
@import url("//unpkg.com/element-ui@1.4.4/lib/theme-default/index.css");
h1{
color: green;
background-color: black;
text-align: center;
font: "Calibri"
}
.el-row {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
}
.el-col {
border-radius: 4px;
}
.bg-purple-dark {
background: #99a9bf;
}
.bg-purple {
background: #d3dce6;
}
.bg-purple-light {
background: #e5e9f2;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.row-bg {
padding: 10px 0;
background-color: #f9fafc;
}