Node.js_express_服务器渲染页面 ejs
服务器渲染页面 ejs
高效的 js 模版引擎
将数据提前渲染到页面上, 再将渲染好的页面返回响应给浏览器
提高首页加载速度
SEO 提前处理,提高加载速度
- 下载 ejs 包
npm install ejs
无需引用,但是要配置模板资源目录
// app.set('views', '模板资源目录');
app.set('views', 'views'); // 通常文件夹 也叫 views
- 基本使用
1. 配置模板资源目录 ( Router 没有 set 方法,所以必须在 主模块下 app.set() )
app.set('views', 'views'); // 通常文件夹 也叫 views
2. 配置要使用的模板引擎 ( Router 没有 set 方法,所以必须在 主模块下 app.set() )
app.set('views engine', 'ejs');
3. 将 后台数据 渲染到 模板资源 上
app.get('/ejs', (request, response)=>{
const data = [{
"name": '孙悟空'.
"age": 555
},{
"name": '白骨精',
"age": 18
}]; response.render('test.ejs', {data}); // .ejs 可以省略
});
4. views/test.ejs
模板语法
1. <% %> 其中可以写任意 js 代码
2. <%= %>
3. <%- %>
源码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head> <body> <% console.log("哈哈"); %>
不会显示到页面上 <%= data[0].name %>
输出指定数据到页面上
不会解析标签,转义 HTML 相关源码后输出
安全性更高 <%- data[1].name %>
输出指定数据到页面上
解析 HTML 源码 一般结合使用:
<% for(var i=0; i<10; i++){ %>
<%= data[i].name %>
<% }; %> </body>
</html>
凡是经过用户输入的东西,都需要进行特殊处理。
- 完善的登录/注册实例
package.json
{
"name": "node_express",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"connect-mongo": "^2.0.3",
"ejs": "^2.6.1",
"express": "^4.16.4",
"mongoose": "^5.4.0",
"sha1": "^1.1.1"
}
}
public/register.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>用户注册</title> <link rel="stylesheet" type="text/css" href="css/index.css"/>
</head> <body>
<div id="outer_box" class="register">
<h2>用户注册</h2>
<form action="http://localhost:3000/register" method="post">
<div class="clothes">
<label for="input_name">用 户 名</label>
<input id="input_name" type="text" name="user_name" placeholder="请输入用户名" />
</div> <div class="clothes">
<label for="input_pwd">密 码</label>
<input id="input_pwd" type="password" name="user_pwd" placeholder="请输入密码" />
</div> <div class="clothes">
<label for="input_repeat_pwd">确认密码</label>
<input id="input_repeat_pwd" type="password" name="user_repeat_pwd" placeholder="请再次输入密码" />
</div> <div class="clothes">
<label for="input_email">注册邮箱</label>
<input id="input_email" type="text" name="user_email" placeholder="请输入邮箱地址" />
</div> <div class="clothes">
<button class="register btn" type="submit">注册</button>
<a class="btn" href="http://localhost:3000/login">
<button type="button">登录</button>
</a>
</div>
</form>
</div>
</body>
</html>
public/login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>用户登录</title> <link rel="stylesheet" type="text/css" href="css/index.css"/>
</head> <body>
<div id="outer_box" class="login">
<h2>用户登录</h2>
<form action="http://localhost:3000/login" method="post">
<div class="clothes">
<label for="input_name">用 户 名</label>
<input id="input_name" type="text" name="user_name" placeholder="请输入用户名" />
</div> <div class="clothes">
<label for="input_pwd">密 码</label>
<input id="input_pwd" type="password" name="user_pwd" placeholder="请输入密码" />
</div> <div class="clothes">
<a class="btn" href="http://localhost:3000/register">
<button type="button">注册</button>
</a>
<button class="login btn" type="submit">登录</button>
</div>
</form>
</div>
</body>
</html>
public/css/index.css
body {
width: 100%;
height: 100%; color: #000;
background: #b9c2a4;
background-size: cover; /* 指定背景图片大小 */
} /*************************************************/
#outer_box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #1a45c3;
} #outer_box.login {
color: #9e098b;
} #outer_box.register {
color: #1a45c3;
} #outer_box>h2{
padding-bottom: 40px;
margin-left: -50px;
} .clothes {
position: relative;
width: 260px;
display: flex;
justify-content: space-between;
margin: 20px 0;
font-size: 18px;
line-height: 32px;
} .tips {
position: absolute;
top:;
right: -100%;
margin-left: -50%;
margin-top: 2px;
width: 252px;
height: 32px;
text-align: center;
color: #f00;
} .clothes>label{
width: 80px;
text-align: center;
} .clothes>input{
width: 170px;
height: 32px;
} button {
width: 100%;
height: 100%; font-size: 16px;
background-color: #c4ceda;
cursor: pointer;
} .clothes .btn{
width: 64px;
height: 32px;
margin: 0 20px;
} .clothes button.register{
background-color: #1a45c3;
color: #fff;
} .clothes button.login{
background-color: #9e098b;
color: #fff;
} #outer_box>h2 {
position: relative;
} #server_info {
display: block;
width: 139px;
height: 20px;
border-radius: 10px; position: absolute;
top:;
right:; color: red;
font-size: 14px;
text-align: center;
line-height: 20px;
background-color: #cecece;
}
views/register.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>用户注册</title> <link rel="stylesheet" type="text/css" href="css/index.css"/>
</head> <body>
<div id="outer_box" class="register">
<h2>用户注册</h2>
<form action="http://localhost:3000/register" method="post">
<div class="clothes">
<label for="input_name">用 户 名</label>
<input id="input_name" type="text" name="user_name" placeholder="请输入用户名" />
<div class="tips"><%= errInfo.name %></div>
</div> <div class="clothes">
<label for="input_pwd">密 码</label>
<input id="input_pwd" type="password" name="user_pwd" placeholder="请输入密码" />
<div class="tips"><%= errInfo.password %></div>
</div> <div class="clothes">
<label for="input_repeat_pwd">确认密码</label>
<input id="input_repeat_pwd" type="password" name="user_repeat_pwd" placeholder="请再次输入密码" />
<div class="tips"><%= errInfo.repeatPassword %></div>
</div> <div class="clothes">
<label for="input_email">注册邮箱</label>
<input id="input_email" type="text" name="user_email" placeholder="请输入邮箱地址" />
<div class="tips"><%= errInfo.email %></div>
</div> <div class="clothes">
<button class="register btn" type="submit">注册</button>
<a class="btn" href="http://localhost:3000/login">
<button type="button">登录</button>
</a>
</div>
</form>
</div>
</body>
</html>
views/login.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>用户登录</title> <link rel="stylesheet" type="text/css" href="css/index.css"/>
</head> <body>
<div id="outer_box" class="login">
<h2>
用户登录
<div id="server_info">
<%= data.info %>
</div>
</h2>
<form action="http://localhost:3000/login" method="post">
<div class="clothes">
<label for="input_name">用 户 名</label>
<input id="input_name" type="text" name="user_name" placeholder="请输入用户名" />
</div> <div class="clothes">
<label for="input_pwd">密 码</label>
<input id="input_pwd" type="password" name="user_pwd" placeholder="请输入密码" />
</div> <div class="clothes">
<a class="btn" href="http://localhost:3000/register">
<button type="button">注册</button>
</a>
<button class="login btn" type="submit">登录</button>
</div>
</form>
</div>
</body>
</html>
db/connectDB.js
const mongoose = require('mongoose'); module.exports = new Promise((resolve, reject)=>{
mongoose.connect('mongodb://localhost:27017/user_database', {useNewUrlParser:true})
mongoose.connection.once('open', err=>{
if(err){
console.log(err);
reject(err);
}else{
resolve('数据库已连接');
};
});
});
models/userModel.js
const mongoose = require('mongoose'); const Schema = mongoose.Schema;
const fieldSchema = new Schema({
"userName": {
"type": String,
"unique": true,
"required": true
},
"userPassword": {
"type": String,
"required": true
},
"userEmail": {
"type": String,
"unique": true,
"required": true
},
"createTime": {
"type": Date,
"default": Date.now()
}
}); module.exports = mongoose.model("user_info", fieldSchema);
routers/get/index_router.js
const express = require('express');
const {resolve} = require('path'); const indexRouter = new express.Router(); /************************ get ***********************/
indexRouter.get('/', (request, response)=>{
response.sendFile(resolve(__dirname, '../../public/login.html'));
}); indexRouter.get('/login', (request, response)=>{
response.sendFile(resolve(__dirname, '../../public/login.html'));
}); indexRouter.get('/register', (request, response)=>{
response.sendFile(resolve(__dirname, '../../public/register.html'));
}); module.exports = indexRouter;
routers/post/form_router.js
const express = require('express');
const sha1 = require('sha1'); const promiseConnect = require('../../db/connectDB.js');
const userInfoModel = require('../../models/userModel.js'); const formRouter = new express.Router(); /************************ post ***********************/
let logged = false ;
promiseConnect.then(async result=>{
console.log(result); formRouter.post('/register', async (request, response)=>{
const {
user_name:uName,
user_pwd:uPwd,
user_repeat_pwd:urePwd,
user_email:uEmail,
} = request.body; /**** 解构赋值 ****/ userInfo = {
"userName": uName,
"userPassword": uPwd,
"userEmail": uEmail
}; let errInfo = {}; if(urePwd !== uPwd){
errInfo.repeatPassword = '密码两次输入不一致';
};
if(!(/^[a-zA-Z][a-zA-Z0-9_]{5,20}$/.test(uName))){
errInfo.name = '用户名不合法';
};
if(!(/^[a-zA-Z0-9_]{6,20}$/.test(uPwd))){
errInfo.password = '密码不合法';
};
if(!(/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(uEmail))){
errInfo.email = '邮箱不合法';
}; const fond = await userInfoModel.findOne({"userName": uName});
if(fond){
errInfo.name = '用户名已被注册';
}; const badEmail = await userInfoModel.findOne({"userEmail": uEmail});
if(badEmail){
errInfo.email = '邮箱已被注册';
}; let data = {errInfo};
if(errInfo.repeatPassword || errInfo.name || errInfo.password || errInfo.email){
response.render('register.ejs', data);
return;
}else{
userInfo.userPassword = sha1(userInfo.userPassword);
await userInfoModel.create(userInfo);
data.info = "注册成功";
response.render('login.ejs', {data});
};
}); formRouter.post('/login',async (request, response)=>{
logged = false;
let uName = request.body['user_name'];
let uPwd = request.body['user_pwd'];
userInfo = {
"userName": uName,
"userPassword": uPwd
}; if(!(/^[a-zA-Z][a-zA-Z0-9_]{5,20}$/.test(uName))){
logged = false; // 用户名不存在
}else if(!(/^[a-zA-Z0-9_]{6,20}$/.test(uPwd))){
logged = false; // 密码错误
}; const findName = await userInfoModel.findOne({"userName": uName});
const findPwd = await userInfoModel.findOne({"userPassword": sha1(uPwd)});
if(findName && findPwd){
logged = true;
}; let data = {};
logged?(data.info='登录成功'):(data.info='用户名或密码错误');
response.render('login.ejs', {data});
});
}).catch(err=>console.log(err)); module.exports = formRouter;
index.js
const express = require('express');
const app = express(); const indexRouter = require('./routers/get/index_router.js');
const formRouter = require('./routers/post/form_router.js'); app.set('views', 'views'); // 1. 配置模板路径
app.set('view engine', 'ejs'); // 2. 配置模板引擎
/*********************** 中间件 **********************/
// 暴露路由 login.html register.html
app.use(express.static('public')); // 默认调用 next(); // 将 用户输入的数据 挂载到 请求体 request.body 上
app.use(express.urlencoded({extended: true})); // 默认调用 next(); app.use(indexRouter);
app.use(formRouter); /**************** 端口号 3000, 启动服务器 ***************/
app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\nHunting Happy!'));
Node.js_express_服务器渲染页面 ejs的更多相关文章
- 从零开始,做一个NodeJS博客(四):服务器渲染页面与Pjax
标签: NodeJS 0 一个星期没更新了 = = 一直在忙着重构代码,以及解决重构后出现的各种bug 现在CSS也有一点了,是时候把遇到的各种坑盘点一下了 1 听歌排行 API 修复与重构 1.1 ...
- 10_常见的get和post请求_路由器_ejs服务器渲染模板引擎
1. 常见的 get 和 post 请求有哪些? 常见的发送 get 请求方式: 在浏览器地址栏输入 url 地址访问 所有的标签默认发送的是 get 请求:如 script link img a f ...
- 从单页应用(SPA)到服务器渲染(SSR)
从单页应用(SPA)到服务器渲染(SSR) 情景回顾 在学习Vue开发一个电商网站的管理后台时,使用到了一个组件 vue-quill-editor 主要是一个快捷的一个富文本编辑器 在使用这个组件的组 ...
- node.js 的页面渲染方法ejs
.安装依赖的组件 npm i consolidate -D npm i ejs -D 2.布局服务端 const express = require('express'); const consoli ...
- 单页面(如react,vue)网站的服务器渲染 SSR 之 SEO 大杀器 Rendertron
单页面网站,比如vue.recat框架的网站,一般都是直接从服务器推送index.html,再根据自身路由通过js在客户端浏览器渲染出完整的html页面. 但是搜索引擎的爬虫可没有这么智能(实际上go ...
- React Router 按需加载+服务器渲染的闪屏问题
伴随着React协议的『妥协』(v16采用MIT),React为项目的主体,这个在短期内是不会改变的了,在平时使用过程中发现了如下这个问题: 在服务器渲染的时候,刷新页面会出现闪屏的现象(白屏一闪而过 ...
- Asp .Net Core Spa (二) - 服务器渲染1
Server Side Rendering 服务器渲染是各 Spa 项目目前很热衷于解决的一个问题,毕竟针对SEO和首次加载优化 .Net Core SPA 服务器渲染 将分为 两篇: 第一篇 主要分 ...
- node服务端渲染(完整demo)
简介 nodejs搭建多页面服务端渲染 技术点 koa 搭建服务 koa-router 创建页面路由 nunjucks 模板引擎组合html webpack打包多页面 node端异步请求 服务端日志打 ...
- React 服务器渲染原理解析与实践
第1章 服务器端渲染基础本章主要讲解客户端与服务器端渲染的概念,分析客户端渲染和服务器端渲染的利弊,带大家对服务器端渲染有一个粗浅认识. 1-1 课程导学1-2 什么是服务器端渲染1-3 什么是客户端 ...
随机推荐
- Mac 终端美化方法
美化终端,主要是主题,字体,命令行提示3个方面. 主题 使用的主题是Solarized Dark主题. 安装主题: git clone git://github.com/altercation/sol ...
- LFYZ-OJ ID: 1021 邮票问题
邮票问题 Problem Description 设有已知面额的邮票m种,每种有n张,用总数不超过n张的邮票,能从面额1开始,最多连续组成多少面额.(1≤m≤100,1≤n≤100,1≤邮票面额≤25 ...
- redis远程连接报错记录
错误如下 redis可视化工具连接测试 telnet ip 6379 修改关键参数如下 #开通外网访问 # bind 127.0.0.1 #以后台方式运行 daemonize no #取消保护模式,保 ...
- 我的 Erdos 数是 4
我的 Erdos 数是 4. 呵呵. 图书馆开通了一个月的 mathscinet 数据库查询. 本来想买个 pde 的最新进展, 结果不能查询, 就算了.
- Jenkins 子业务日志拆分分析方法
需求 Jenkins日志打印内容很长,或者并发编译导致,日志内容不容易查看. 对于具体业务失败, 开发者希望看到具体业务自身的日志内容. 解法 tee 命令能够保证, shell命令执行的内容,即往控 ...
- ES7 and ES8 特性
ES7 特性:1.Array.prototype.includes let arr = ['react', 'angular', 'vue'] // Correct if (arr.includes( ...
- dubbo线程模型
dubbo的provider有2种线程池: IO处理线程池.(直接通过netty等来配置) 服务调用线程池. 如果事件处理的逻辑能迅速完成,并且不会发起新的 IO 请求,比如只是在内存中记个标识,则直 ...
- lucene学习的小结
pom.xml设置 <dependency> <groupId>junit</groupId> <artifactId>junit</artifa ...
- python加密
""#line:4 __all__ =[]#line:6 class OO0O0O000O0O0O000 :#line:8 ""#line:9 def __in ...
- Tomcat:3DES解密时中文乱码
情况说明:直接用main方法运行时是没有问题的,web程序一放入tomcat中就会出现解密时乱码. 解决办法: 在解密时,返回string时对数组需要指定UTF-8编码. public static ...