此元素会作为内联表格来显示(类似 ),表格前后没有换行符
table-row-group
此元素会作为一个或多个行的分组来显示(类似 )
table-header-group
此元素会作为一个或多个行的分组来显示(类似 )
table-footer-group
此元素会作为一个或多个行的分组来显示(类似 )
table-row
此元素会作为一个表格行显示(类似 )
table-column-group
此元素会作为一个或多个列的分组来显示(类似 )
table-column
此元素会作为一个单元格列显示(类似 )
table-cell
此元素会作为一个表格单元格显示(类似 和 )
table-caption
此元素会作为一个表格标题显示(类似 )
inherit
规定应该从父元素继承 display 属性的值。
特别注意,在CSS中使用display: flex这一属性可以实现弹性布局效果。这是一种近年来引入的新特性。通过设置此属性值,在父级容器中可以选择是否允许子元素换行
3.4 border
border: 1px solid; /* 边框大小1px 边框形状为直线 */
border-radius: 2px; /* 设置边框角落圆弧半径 */
3.5 line-height
将其设置成和元素高度一致可使得文字垂直居中,如
div {
height: 36px;
line-height: 36px;
}
3.6 outline
设置 outline: none; 可以去除一些元素在被选中时的边框
3.7 cursor
设置鼠标指向该元素时的形状,如 cursor: pointer; 设置为指针状
3.8 自动计算宽度和高度
在某些情况下(例如当所指定的宽度或高度超过了父容器的实际尺寸时),为元素指定特定的宽度和高度可能会导致溢出问题。此时建议使用 CSS 的自动 sizing 功能来处理这个问题
...
<li>
<input style="width: 60%;">
<input style="width: calc(100% - 60%); height: auto;">
</li>
...
4. jQuery
4.1 Ajax
Ajax 全称 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)
Ajax 不是新的编程语言,而是一种使用现有标准的新方法
Ajax的主要优势是可以无需完整页面 reload 即通过与服务器的数据交换来实现对部分网页内容的更新
Ajax无需安装任何浏览器插件,并且使用时必须确保用户同意让JavaScript在浏览器中执行
一般语法:
$.ajax({
method: 'post',
url: '',
data: {},
success: function() {},
error: function(err) {},
...
});
4.2 语法
jQuery 语法是通过选取 HTML 元素,并对选取的元素执行某些操作
基础语法:$(selector).action()
美元符号用于定义JavaScript变量的类型。
选择器(selector)'查询'和'查找'用于定位HTML元素。
jQuery 的 action()方法用于实现对HTML元素的操作。
实例:
该函数旨在实现对当前元素的隐藏操作。
此处代码用于实现对所有元素的遮蔽功能。
通过此代码段可实现仅对具有class="test"属性的所有元素进行遮蔽处理。
使用此JavaScript语句可实现针对id="test"对象的具体遮蔽操作。
4.3 HTML相关
4.3.1 捕获元素相关属性
text(): 获取所选元素的文本内容。
html(): 获取所选元素的HTML标记。
val(): 获取表单字段的值。
attr() 方法用于提取属性值。
4.3.2 获取 checkbox 是否被选择
var checked = $('#checkbox').prop('checked');
4.4 JQuery实现简单搜索功能并设置关键词高亮
4.4.1 搜索功能
function search() {
//获取关键词
var value = $.trim($('#search_text').val());
//获取要搜索处的父级元素
var children = $('#comments_container').children();
//对每一个子级元素进行关键词搜索
children.each(function() {
$(this).hide(); //先将其隐藏
if($(this).text().indexOf(value) >= 0) {
$(this).show(); //匹配成功,显示
}
});
}
4.4.2 关键词高亮
通过 jQuery 第三方插件 highlight(链接)支持关键词高亮功能
<script src="https://johannburkard.de/resources/Johann/jquery.highlight-5.js"></script>
<script>
function search() {
var value = $.trim($('#search_text').val());
var children = $('#comments_container').children();
children.each(function() {
$(this).hide();
$(this).removeHighlight(value);
if($(this).text().indexOf(value) >= 0) {
$(this).highlight(value);
$(this).show();
}
});
}
</script>
5. node.js
5.1 node.js 中的路由机制
在Web开发中广为人知的是,在网页交互中通过GET与POST两种请求方法来实现信息传递。而node.js则特别地支持一种称为路由机制 的技术。这种机制的优势在于无需额外文件即可从前端获取来自后端的数据。例如:
app.get(url, function(req, res) {
...
});
其中 url 实际上是路由器上的一个端口接口,在网络中起到连接作用,在数据传输过程中帮助确定数据的传输路径以及明确应用程序与外部设备之间的通信方向。
为了避免 app.js 中的代码过于冗长且复杂,在开发过程中可能出现维护困难的问题,
我们可以考虑创建一个新的 js 文件,
专门存储与路由相关的代码块。
借助模块化机制,
我们可以实现不同文件之间的高效调用。
//路由文件 router.js
var express = require("express");
var Message = require("./message");
var router = express.Router();
router.post('url', function(req, res) {
...
});
module.exports = router;
//app.js
var path = require('path');
var express = require("express");
var router = require("./router");
var app = express();
app.use(router); //使用路由中的端口
app.use(express.static(path.join(__dirname, "public")));
app.listen(3000, function() {
console.log('Start in port 3000...');
});
module.exports = app;
5.2 回调函数
先举一个栗子:
var fs = require("fs");
function get() {
var Data = "";
fs.readfile(path, function(err, data) {
Data = data;
});
return data;
}
在 node.js 环境中进行操作时采用的是异步机制,在这种情况下,“fs.readfile(...)”会被优先执行并立即返回 "return" 语句。这将导致我们只能获取空字符串而非文件中的实际内容
解决方法:使用回调函数
var fs = require("fs");
function get(callback) {
fs.readfile(path, function(err, data) {
if(err) {
callback(err);
return;
}
callback(err, data);
});
}
get(function(err, data) {
if(err) {
console.log(err);
return;
}
... //对 data 进行处理
});
在 Node.js 环境中,仅能借助回调函数(callback)这一方式才能获取异步函数的数据
5.3 中间件
暂时没有用到,所以理解不是很深刻,其基础形式如下:
app.use(function(req, res, next) {
...
});
在其中使用 next 函数时,在满足特定条件时会依次调用下一个符合条件的中间件;而路由机制正是 Express 中的一种重要的中间件
已知的一种应用是当访问未定义的地址时可通过该机制实现404重定向。由于该中间件采用顺序匹配策略,在所有路由对应的URL均不匹配的情况下,则会触发最后一个中间件。因此,在配置时只需将以下代码放置在所有路由之后即可实现实例中的404重定向。
app.use(function (req, res, next) {
res.render('404.html');
});
5.4 调用其他 node.js 文件中的变量或函数
首先,在需要调用的 js 文件中使用 require
var func = require("func.js");
方法一: 在 func.js 中使用 moudle.exports
function createTime() {
...
}
module.exports = {
createTime: function() {
return createTime();
}
...
};
或者
module.exports = createTime;
方法二: 在 func.js 中使用 exports
exports.createTime = function() {
...
}
5.5 nodemon
安装命令 npm install --global nodemon
一种 node 自动重启插件能够监控 app.js 中的变化,并在用户按下保存时自动触发 restart 事件以重新加载应用文件
5.6 express
一种框架,用于加载公用、静态资源,可处理 get/post 请求
var path = require('path');
var express = require("express");
var app = express();
app.use(express.static(path.join(__dirname, "public")));
app.get('/GetMessage', function(req, res) {
...
});
app.post('/PostMessage', function(req, res) {
...
});
app.listen(3000, function() {
console.log('Start in port 3000...');
});
5.7 fs
用于读写文件
//read file
fs.readFile("message.json", 'utf8', function(err, data) {
if(err) {
console.log(err);
res.status(404).send(err);
}
res.send(JSON.parse(data));
});
//write file
fs.writeFile("message.json", JSON.stringify(data), function(err) {
if(err) {
console.log(err);
res.status(404).send(err);
}
res.send();
});
5.8 querystring
用于解析 post 请求中的参数
app.post('/PostMessage', function(req, res) {
var comment = "";
req.on('data', function(data) {
comment += data;
});
res.on('end', function(req, res) {
//parse用于将其解析为对象
var comment1 = querystring.parse用于将其解析为对象(comment);
//stringify用于将其解析为字符串
var comment2 = querystring.stringify(comment);
res.send();
});
});
由于 JavaScript 中的函数通常以异步方式执行,在res.on(…)事件处理钩子中定义的所有回调函数都需要执行。因此,在res.on(…)事件处理钩子中定义的所有回调函数都需要执行。此外,在进行文件操作时,默认建议先读取后再进行其他操作,并将这些写入操作放置在相应的读取操作之后。
app.post('/SendMessage', function(req, res) {
var comment = "";
req.on('data', function(data) {
comment += data;
});
req.on('end', function() {
fs.readFile("message.json", 'utf8', function(err, data) {
if(err) {
console.log(err);
fs.writeFile("message.json", JSON.stringify([]), function(err) {
if(err) {
console.log(err);
res.status(404).send(err);
}
res.send();
});
res.status(404).send(err);
}
fs.writeFile("message.json", "", function(err) {
if(err) {
console.log(err);
res.status(404).send(err);
}
res.send();
});
});
});
});
5.9 nodemailer
自动收发邮件的第三方包,其用法如下:
var nodemalier = require("nodemailer");
var mailTransport = nodemalier.createTransport({
service: "qq",
secureConnection: true,
auth : {
user : '发送者邮箱',
pass : 'SMTP授权码'
}
});
router.get('/SendEmail', function(req, res) {
Email_code = Message.CreateEmailCode();
var options = {
from: "发送者 <发送者邮箱>",
to: '接收者邮箱',
subject: "邮件标题",
html: "邮件内容,支持html语法"
};
mailTransport.sendMail(options, (err, info) => {
...
});
});
5.10 mysql
node.js 连接本地 mysql 数据库的第三方包,其用法如下:
var mysql = require("mysql");
var connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "root",
database: "database",
port: 3306,
dateStrings: true
});
//查询
exports.login = function(info, callback) {
var sql = "select * from user where (username = '" + info.username + "' or email = '" + info.username + "') and password = '" + info.password + "';";
connection.query(sql, function(err, result) {
if(err) {
console.log(err);
callback(err);
}
callback(null, result[0].username);
});
};
//插入
exports.register = function(data, callback) {
var sql = "insert user(username, password, email, createtime) values(?, ?, ?, ?);";
connection.query(sql, [data.username, data.password, data.email, data.createtime], function(err) {
if(err) {
callback(err);
return;
}
callback(null);
});
};
//删除
exports.deletemessage = function(username, id, callback) {
var sql = "delete from message where username = ? and id = ?;";
connection.query(sql, [username, id], function(err, result) {
if(err) {
callback(err);
return;
}
callback(null, result.affectedRows);
});
}
//修改
exports.changepassword = function(username, new_password, callback) {
var sql = "update user set password = ? where (username = ? or email = ?);";
connection.query(sql, [new_password, username, username], function(err, result) {
if(err) {
callback(err);
return;
}
callback(null, result.affectedRows);
});
}
5.11 express-session
用于将用户的数据保存到服务端,如记住密码等
//一定要将其放在使用路由之前
app.use(session({
secret: 'CUG_YZL', //加密字符串
cookie: {
httpOnly: true, //是否禁止在前端通过 JS 代码进行修改
maxAge: 1000 * 60 * 60 * 24 //session 保存的最大时间
},
rolling: true, //当用户在页面有操作时自动更新 session 失效时间
resave: true, //允许重复保存
//是否强制将未初始化的 session 存储(不知道什么意思,只知道 rolling 为 true 时候其必须为 false)
saveUninitialized: false
}));
如果想要在重新提交请求是修改其有效时间,可以采用以下这种办法:
router.post('/Login', function(req, res) {
var data = "";
req.on('data', function(chunk) {
data += chunk;
});
req.on('end', function() {
...
var hour = 1000 * 60 * 60 * 24 * 30;
req.session.cookie.expires = new Date(Date.now() + hour); //修改其到期时间
req.session.cookie.maxAge = 100 * hour; //修改其有效时间
...
});
});
5.12 crypto
一种加密算法,一般用于对用户密码进行加密操作
var crypto = require("crypto");
const hash_key = "AVs5pq";
router.post('/Login', function(req, res) {
var data = "";
req.on('data', function(chunk) {
data += chunk;
});
req.on('end', function() {
data = querystring.parse(data);
//注意每次加密时都要重新定义一个 md5
var md5 = crypto.createHash("md5", hash_key);
data.password = md5.update(data.password).digest("hex");
...
});
});
6. art-template
一种渲染框架
<body>
<div id="comment">
<div id="head">
<h1>留言板</h1>
<button onclick="javascript:window.location.href='./html/comment.html'">写留言</a></button>
</div>
<div id="comments_container">
<ul>
{{ each comments }}
<li class="newslist">
{{ $value.name }}说: {{ $value.message }}
<span>{{ $value.datatime }}</span>
</li>
{{ /each }}
</ul>
</div>
</div>
</body>
<script>
window.onload = function() {
$.ajax({
method: "get",
url: "/GetMessage",
data: {},
success: function(data) {
var ret = template('comment', {
comments: data
});
document.getElementById('comment').innerHTML = ret;
},
error: function(err) {
console.log(err);
}
});
};
</script>
要禁止字符串转义可以使用 {{@value}},注意千万不要加空格,否则会报错
6.1 与table不兼容问题
问题描述
在一个项目中,使用 art-template 对 table 内的单元格进行渲染,报错如下:
template-web.js:2 Uncaught TemplateError: comment:21:33
19| </thead>
20| <tbody><tr>
>> 21| <td>{{ $value.name }}</td>
22| <td>{{ $value.message }}</td>
23| <td>{{ $value.datatime }}</td>
24| </tr></tbody>
RuntimeError: Cannot read property 'name' of undefined
核心代码如下:
...
<table style="margin-top: 10px;">
<thead>
<tr>
<td><b>发言者</b></td>
<td><b>内容</b></td>
<td><b>发布时间</b></td>
</tr>
</thead>
<tbody>
{{ each comments }}
<tr>
<td>{{ $value.name }}</td>
<td>{{ $value.message }}</td>
<td>{{ $value.datatime }}</td>
</tr>
{{ /each }}
</tbody>
</table>
...
解决方案
通过 <script type="text/html" id="..."></script> 标签对 table 模块的代码进行包裹,并在 js 代码中实现对相关属性的实时更新
具体实例如下:
...
<div id="comments_container">
<script type="text/html" style="display: none;" id="Table"></script>
<table style="margin-top: 10px;">
<thead>
<tr>
<td><b>发言者</b></td>
<td><b>内容</b></td>
<td><b>发布时间</b></td>
</tr>
</thead>
<tbody>
{{ each comments }}
<tr>
<td>{{ $value.name }}</td>
<td>{{ $value.message }}</td>
<td>{{ $value.datatime }}</td>
</tr>
{{ /each }}
</tbody>
</table>
</script>
</div>
...
<script>
window.onload = function() {
$.ajax({
method: "get",
url: "/GetMessage",
data: {},
success: function(data) {
var ret = template('comment', {
comments: data
});
document.getElementById('comment').innerHTML = ret;
document.getElementById("comments_container").innerHTML = document.getElementById("Table").innerHTML;
},
error: function(err) {
console.log(err);
}
});
};
</script>
7. express-art-template
此艺术模板与表达式结合的渲染工具,在后端通过res.render(url, data)方法跳转至相应页面并进行渲染,并且允许配置模板以实现特定效果。支持设置模板页面的功能,则可显著降低开发效率和复杂度。
7.1 在后端渲染页面
//首先启动引擎,设置渲染格式为 html
app.engine("html", require("express-art-template"));
//设置渲染目录,在访问时会自动将该页面放至根目录
app.set("views", path.join(__dirname, "/views/"));
//对根目录进行渲染
app.get('/', function(req, res) {
Message.getmessage(function(err, data) {
if(err) {
console.log(err);
res.render("404.html");
return;
}
//跳转并渲染
res.render("index.html", {
comments: data
});
});
});
7.2 模板页面的使用
可以通过提取某些页面的公共模块并利用动态加载技术来优化网页构建流程,在此过程中能够大幅减少所需编写的手动代码量。
<!-- 模板页面 layout.html -->
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="./public/css/style.css">
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="./public/js/main.js"></script>
{{ block 'head' }} {{ /block }}
</head>
<body>
{{ block 'header' }} {{ /block }}
{{ block 'content' }} {{ /block }}
{{ include '../_partitals/footer.html' }}
</body>
{{ block 'script' }} {{ /block }}
</html>
<!-- 底部 footer.html -->
<div id="copyright">
...
</div>
<!-- 首页 index.html -->
{{ extend './_layout/layout.html' }}
{{ block 'head' }}
<title>留言板</title>
{{ /block }}
{{ block 'header' }}
<div id="head">
<h1>留言板</h1>
<button onclick="javascript:window.location.href='comment'">写留言</a></button>
</div>
{{ /block }}
{{ block 'content' }}
<div id="comments_container">
<hr/>
{{ each comments }}
<div style="text-align: left; margin-left: 10px;">
<b>@{{ $value.name }}</b>
<span style="font-size: 14px;">{{ $value.datatime }}</span>
<p> {{ $value.message }}</p>
</div>
<hr/>
{{ /each }}
</div>
{{ /block }}
其中用来包含外部内容的 {{ include ... }是用来包含外部内容的占位符语法,在Markdown中用来加载其他页面;而 {{ block ... }是用来构建自定义组件的占位符语法,在Markdown中被用来构建自定义模块;另外 {{ extend ... }则是用来继承样式表和行为的占位符语法,在Markdown中被用来继承模板页面的行为
8. node.js 项目结构
|-- node_moudles 用于存放 node.js 的第三方包
|-- public 用于存放静态资源
|-- js 用于存放 JavaScript 代码
|-- css 用于存放 css 样式文件
|-- img 用于存放图片、logo等
|-- views 用于存放视图目录
|-- _layout 用于存放底层页面模板
|-- _paritals 用于存放某些页面的公共部分,如:header.html
|-- 其他
|- index.html
|-- routes 用于存放路由文件
|- app.js 监听文件
|- pakege.json 包描述文件,可使用npm init 命令生成
|- pakege-lock.json 第三方包版本锁定文件(npm 5 以上版本可用)
|- README.md 项目说明文档
9. 同步和异步问题
故名之思议,则同步即指程序按顺序执行;而异步则系操作系统调度机制导致代码非顺序执行。其中涉及的文件读写等问题等皆可参考前述讨论
问了解决这个问题,我们引入了 promise 工具
promise 负责管理异步操作队列,并按照用户的指定顺序执行任务后返回预期结果.
promise 有三种状态:
pending
待定状态,操作处于队列中,等待处理
fulfilled
成功状态,操作已被成功执行
rejected
执行失败
Promise只能处在一个状态,并在其发生更改时立即启动then函数中的后续步骤
简单实例如下:
var p = new Promise(function(resolve, reject) {
...
if(success) {
resolve(data);
}
else {
reject(err);
}
});
p.then(function(data) {
console.log(data);
}, function(err) {
console.log(err);
});
promise在创建之后会立刻执行内部所定义的函数,并将计算后的结果值代入then 中的后续操作中进行处理。
10. 其他
10.1 node.js 读取文件失败
var datapath = "./message.json"
将相对路径改为绝对路径
var path = require("path");
var datapath = path.join(__dirname, "/message.json");
10.2 判断是否为 PC 端
function IsPC() {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"];
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
10.3 生成验证码
var array = new Array();
var verify_code = "";
function init() {
var cnt = 0;
for(var i = 0; i < 10; ++i) array[cnt++] = i;
for(var i = 65; i < 91; ++i) array[cnt++] = String.fromCharCode(i);
for(var i = 97; i < 123; ++i) array[cnt++] = String.fromCharCode(i);
}
//以下内容参考至
function change_code() {
var img = document.getElementById("verify_img");
var canvas = document.createElement("canvas");
var width = img.clientWidth;
var height = img.clientHeight;
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext("2d");
var len = array.length;
verify_code = "";
var length = 5;
//生成随机字母并将其旋转后显示在图像上
for(var i = 0; i < length; ++i) {
var alpha = array[Math.floor(Math.random() * len)];
var angle = Math.random() * 20 * Math.PI / 100; //产生0~20内的随机角度
angle = Math.random() < 0.5 ? angle : -angle;
verify_code += alpha;
var x = 10 + i * width / length;
var y = Math.min(Math.max(0.6 * height + Math.random() * 10 * (Math.random() < 0.5 ? 1 : -1), 0.4 * height), 0.8 * height);
context.font = "bold 20px console";
context.translate(x, y);
context.rotate(angle);
context.fillstyle = randomColor();
context.fillText(alpha, 0, 0);
context.rotate(-angle);
context.translate(-x, -y);
}
//生成随机线条
for(var i = 0; i < 10; ++i) {
context.strokeStyle = randomColor();
//从(0, 0)开始
context.beginPath();
//将画笔移动至随机位置
context.moveTo(Math.random() * width, Math.random() * height);
//画出一条随机线条
context.lineTo(Math.random() * width, Math.random() * height);
context.stroke();
}
//生成随机小点
for(var i = 0; i < 10; ++i) {
context.strokeStyle = randomColor();
context.beginPath();
var x = Math.random() * width;
var y = Math.random() * height;
context.moveTo(x, y);
context.lineTo(x + 1, y + 1);
context.stroke();
}
img.src = canvas.toDataURL("image/png");
verify_code = verify_code.toLowerCase();
}
function randomColor() {
var R = Math.floor(Math.random() * 256);
var G = Math.floor(Math.random() * 256);
var B = Math.floor(Math.random() * 256);
return "rgb(" + R + ", " + G + ", " + B + ")";
}
10.4 Ajax 提交时 Json 会被转成字符串
如果要判断 bool 类型,应当使用 Bool == 'true' 来判断
10.5 JS 获取当前时间
function pushzero(number) {
return number < 10 ? "0" + number : number;
}
function createTime() {
var date = new Date();
var arr = [pushzero(date.getFullYear()) + "-",
pushzero(date.getMonth() + 1) + "-",
pushzero(date.getDate()) + " ",
pushzero(date.getHours()) + ":",
pushzero(date.getMinutes()) + ":",
pushzero(date.getSeconds())];
return arr.join("");
}
10.6 设置页面为中文的方法
zh-CN 已经被废弃了,应该使用 zh-cmn-Hans
<html lang="zh-cmn-Hans">
全部评论 (0 )
© 2024 技术社区 .All Rights Reserved.