Advertisement

Web前端学习笔记

阅读量:

Web前端学习笔记

1. 格式或命名问题

当JavaScript代码触发页面中的元素时,请将script代码放置到最后以确保在页面尚未完全加载的情况下无法导致无法获取元素的情况发生。

css 引入格式如下:

复制代码
    <link rel="stylesheet" type="text/css" href="">

为元素中添加事件时(例如,在 button 元素中的点击时间),避免与 window 内内置的功能名称冲突,这可能会导致无法正常执行或其他问题。

为元素中添加事件时(例如,在 button 元素中的点击时间),避免与 window 内内置的功能名称冲突,这可能会导致无法正常执行或其他问题。

复制代码
    <input type="button" value="清空" onclick="clear()">

此时点击按钮后函数不会执行,因为 clear 与 window 中的 clear 重名

2. 标签样式及属性问题

2.1 table

2.1.1 单元格合并
复制代码
    <td colspan="x"></td>	<!-- 表示将该单元格与前 x-1 个列单元格合并 -->
    <td rowspan="x"></td>	<!-- 表示将该单元格与后 x-1 个行单元格合并 -->
2.1.2 表格居中
复制代码
    <talbe style="margin: 0 auto; text-align: center;"></table>
2.1.3 表格以及单元格边框
复制代码
    td {
    border: 1px solid;
    }
    table {
    border: 1px solid;
    }

1px: 边框大小 solid: 直线

2.2 textarea

2.2.1 禁止拉伸样式

将其 style 样式中的 resize 设置为 none 即可

2.2.2 设置所填字符串最大/最小长度
复制代码
    <textarea minlength="3" maxlength="100"></textarea>

该属性只在其在表单中,且点击提交表单按钮时生效

2.2.3 设置为必填项

向其中加入 required属性

该属性只在其在表单中,且点击提交表单按钮时生效

2.3 form

2.3.1 提交问题

传统提交方法

复制代码
    <form action="" method=""></form>
属性 描述
accept MIME_type HTML 5 中不支持
accept-charset charset_list 规定服务器可处理的表单数据字符集
action URL 规定当提交表单时向何处发送表单数据

| autocomplete| on
off| 规定是否启用表单的自动完成功能 |
|enctype|见说明|规定在发送表单数据之前如何对其进行编码|

| method| get
post| 规定用于发送 form-data 的 HTTP 方法 |

name form_name 规定表单的名称

| target| _blank
_self_parent
_top
framename| 规定在何处打开 action URL |

复制代码
2. 

使用 Ajax

复制代码
        $("form").submit(function() {

            $.ajax({
                method: 'post',
                url: '',
                data: {},
                success: function() {},
                error: function(err) {},
                ...
            });
        });
2.3.2 form表单提交的原生事件

form表单在提交时会触发一个内置于浏览器的行为——页面自然重载。如果采用Ajax方法并在表单提交后进行其他处理,请注意此时事件是非阻塞的——可能会出现页面重载后再执行你的函数

实例如下:

复制代码
    ...
    <script>
    function sendmessage() {
        $.ajax({
            method: 'post',
            url: '/SendMessage',
            data: {...},
            success: function() {
                alert("提交成功");
                window.location = "/";
            },
            error: function(err) {
                alert("提交失败,请刷新重试");
                console.log(err);
            }
        });
    }
    $("form").submit(function() {
        sendmessage();
    });
    </script>
    ...

此时 success 中的函数有一定几率被跳过

解决方法

使用 e.preventDefault() 函数阻止原生事件的发生

修改如下:

复制代码
    $("form").submit(function(e) {
    sendmessage();
    e.preventDefault();
    });

2.4 input

复制代码
    <input placeholder="提示内容" type="text" autocomplete="off" required maxlength="10" minlength="6">

placeholder

提示内容

type

类型

autocomplete

是否记忆化

required

作为表单的必填项

maxlength

最大字符长度

minlength

最小字符长度

2.5 label

将两个元素绑定起来,经常与 checkbox 连用,增强用户体验,如:

复制代码
    <input type="checkbox" id="remember_me">
    <label for="remember_me">下次自动登录</label>

2.6 ul(ol)

去除缩进

复制代码
    ul {
    margin: 0;
    padding: 0;
    }

2.7 li

去除标签前的标识符

复制代码
    li {
    list-style: none;
    margin: 10px 0;
    }

3. CSS

3.1 margin

复制代码
    /* 应用于所有边 */
    margin: 1em;
    margin: -3px;
    
    /* 上边下边 | 左边右边 */
    margin: 5% auto;
    
    /* 上边 | 左边右边 | 下边 */
    margin: 1em auto 2em;
    
    /* 上边 | 右边 | 下边 | 左边 */
    margin: 2px 1em 0 auto;
    
    /* 全局值 */
    margin: inherit;
    margin: initial;
    margin: unset;

该属性允许设置从1到4个不同的数值参数;每个参数可以指定为一个具体的长度、百分比缩放因子或自动模式;当数值为负时,默认情况下该元素会靠近其相邻的兄弟元素

  • 当仅设置单一数值时,则该值将均匀分配给所有四条边界
    • 若设定两个数值,则前一数值将被赋于上下两条边缘宽度
    • 而后一则用于左右两条边缘宽度
    • 当设定三个参数,则第一参数决定上边缘宽度
    • 第二参数则被赋于左右两边框宽度
    • 第三参数则决定下边缘宽度
    • 最后一种情况即设定四个参数,则它们将分别对应上方框、右边框、下方框与左边框的大小

length

​ 以固定值为外边距

percentage

​ 相对于包含块的 宽度 ,以百分比值为外边距

auto

由浏览器自行决定设置适当宽度的外边距。在某些特定场景下(如特殊设计需求),该数值能够让元素居中。

3.2 vertical-align

用于设置元素标签在垂直方向上的位置,一般将其设置为 middle

3.3 display

描述
none 此元素不会被显示
block 此元素将显示为块级元素,此元素前后会带有换行符
inline 默认。此元素会被显示为内联元素,元素前后没有换行符
inline-block 行内块元素。(CSS2.1 新增的值)
list-item 此元素会作为列表显示
run-in 此元素会根据上下文作为块级元素或内联元素显示
compact CSS 中有值 compact,不过由于缺乏广泛支持,已经从 CSS2.1 中删除
marker CSS 中有值 marker,不过由于缺乏广泛支持,已经从 CSS2.1 中删除
table 此元素会作为块级表格来显示(类似 ),表格前后带有换行符
inline-table 此元素会作为内联表格来显示(类似 ),表格前后没有换行符))))))
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开发中广为人知的是,在网页交互中通过GETPOST两种请求方法来实现信息传递。而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>&emsp;{{ $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)

还没有任何评论哟~