第一节
1.请求资源
- 异步请求:
- 数据: 字符串、数字、JSON、XML
- 文件(视频、音频、文本文件、HTML/JS/CSS/...)
2.请求的前提
- 1.一定要有资源
- 2.资源的来源 -> 服务器(本质就是台电脑)
- 3.有地址 -> API/URI(资源定位)
- 通过一个资源定位在服务器上找到某个特定的资源
3.响应的前提
- 1.服务器允许请求
- 2.确认有资源定位对应的资源
- 3.将这个资源返回给 请求方(浏览器or服务器)
4.资源是拿来干嘛的?
- 页面 -> html -> 服务器(所有的资源其实都是在服务器上)
- 请求服务器响应这个资源HTML -> 将HTML响应回客户端 -> 下载这个文件的过程/加载这个文件编码的过程
- HTML编码 -> 浏览器 -> 解析
- link -> 下载css文件
- body -> 解析HTML -> 组装DOM树
- script -> 阻塞 -> 下载js文件 -> 解析JS编码 -> 执行
5.WEB项目运行环境问题
- 服务器 -> web 文件夹 / www.xxx.com/test(域名映射到w… -> index.html(假设文件) -> 响应 -> 这样才能访问到
- 静态文件夹 -> 允许你的访问 HTML/CSS/JS/开放的文件 -> 都有浏览器环境运行
前端/后端
- 前端 -> 将资源从服务器上响应回来,在前端运行
- 后端 -> 将资源拿出来直接在服务器里运行
主要在响应:响应回来的就能看到否则看不到
第二节
服务端渲染和js动态渲染
- 服务端渲染: 指的是服务端把数据和HTML整合拼接完整
- 通过http://localhost:8080/html_test 访问
const express = require('express');
const app = express();
const { join } = require('path');
// 设置静态资源目录
app.use(express.static(join(__dirname, 'public')));
app.get('/html_test', (req, res) => {
const title = 'This is a html text';
const list = [
{
id: 1,
name: 'Mike',
age: 6,
score: 6
},
{
id: 2,
name: 'Jodan',
age: 8,
score: 8
},
{
id: 3,
name: 'James',
age: 10,
score: 10
},
];
res.send(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./css/static.css">
</head>
<body>
<div id="app">
<h1>${ title }</h1>
<ul>
${
list.map(item => {
return (
`
<li>
<p>ID:${item.id}</p>
<p>Name:${item.name}</p>
<p>Age:${item.age}</p>
<p>Score:${item.score}</p>
</li>
`
)
}).join(',')
}
</ul>
</div>
<script src="./js/static.js"></script>
</body>
</html>
`)
})
app.listen(8080, (req, res) => console.log("running"))
js动态渲染的格式
- 浏览器拿到对应一个html模板
- 通过下载js脚本,获取标签,进行元素的创建插入等,形成想要的页面构造
// 如html中的script代码如下
const oApp = document.querySelector('#app');
const oContent = document.createElement('p');
oContent.innerHTML = "哈哈哈";
oApp.appendChild(oContent);
服务端渲染和js动态渲染区别
- 前者是后端拼接好返回的html字符串
- 后者是返回一个html文件,再通过加载解析js内部对dom的操作进行渲染
混编模式
http://localhost:8080/index.php
-> 请求 -> URL -> 服务器 -> 映射到这个资源
-> php解释器 -> php文件 -> php源码 -> 执行输出结果给HTML
-> 响应回客户端
问什么js文件不能做到这个,因为浏览器默认认为js是一个脚本
ejs基础使用
const express = require('express');
const app = express();
const { join } = require('path');
// 设置ejs做为模板引擎 默认目录views
app.set('view engine', 'ejs');
// 设置静态资源目录
app.use(express.static(join(__dirname, 'public')));
app.get('/html.ejs', (req, res) => {
res.render('html')// html -> views/html.ejs
})
app.listen(8080, (req, res) => console.log("running"))
- views/html.ejs
<%
const title = 'This is a ejs text';
const list = [
{
id: 1,
name: 'Mike',
age: 6,
score: 6
},
{
id: 2,
name: 'Jodan',
age: 8,
score: 8
},
{
id: 3,
name: 'James',
age: 10,
score: 10
},
];
%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1><%= title %></h1>
<ul>
<% list.map(item => { %>
<li>
<p>ID:<%= item.id %></p>
<p>Name:<%= item.name %></p>
<p>Age:<%= item.age %></p>
<p>Score: <%= item.score %></p>
</li>
<% }) %>
</ul>
</div>
</body>
</html>
可以进行模板拆分以上面为例
- 重复的静态模板部分可以拆分出去, 引用时候 <%- include('模板文件名') %>
- 动态渲染的数据, 引用时候 <%- include('模板文件名', {data}) %>,把data数据传递下去
- 把逻辑和模板抽离出来
- views/top.ejs(静态模板)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
- views/bottom.ejs(静态模板)
</body>
</html>
- views/listitem.ejs(动态模板)
<li>
<p>ID:<%= item.id %></p>
<p>Name:<%= item.name %></p>
<p>Age:<%= item.age %></p>
<p>Score: <%= item.score %></p>
</li>
- views/html.ejs
<%
const title = 'This is a ejs text';
const list = [
{
id: 1,
name: 'Mike',
age: 6,
score: 6
},
{
id: 2,
name: 'Jodan',
age: 8,
score: 8
},
{
id: 3,
name: 'James',
age: 10,
score: 10
},
];
%>
<%- include('top') %>
<div id="app">
<h1><%= title %></h1>
<ul>
<% list.map(item => { %>
<%- include('listitem', {
item
}) %>
<% }) %>
</ul>
</div>
<%- include('bottom') %>
- app.js
const express = require('express');
const app = express();
const { join } = require('path');
// 设置ejs做为模板引擎 默认目录views
app.set('view engine', 'ejs');
// 设置静态资源目录
app.use(express.static(join(__dirname, 'public')));
app.get('/html.ejs', (req, res) => {
const title = 'This is a ejs text';
const list = [
{
id: 1,
name: 'Mike',
age: 6,
score: 6
},
{
id: 2,
name: 'Jodan',
age: 8,
score: 8
},
{
id: 3,
name: 'James',
age: 10,
score: 10
},
];
res.render('html', {
// 传递数据
title,
list
})// html -> views/html.ejs
})
app.listen(8080, (req, res) => console.log("running"))
第三节
抽离MVC层
- 让职责变得明确,该做啥的做啥
一个简单的 列表跳详情页面
- 目录结构如下:
|- controllers (控制器)
| - index.js
|- data(存放的数据目录,后面会用数据库代替)
| - data.json
|- models (模块:`用来处理数据的增删改查等功能的`)
|- index.js
|- libs
|- utils.js公共的方法
|- router(路由模块)
|- views (开放的静态资源)
|- app.js
- app.js
const express = require('express');
const app = express();
const { join } = require('path');
const router = require('./router');
app.use(router);
// 设置ejs做为模板引擎 默认目录views
app.set('view engine', 'ejs');
// 设置静态资源目录
app.use(express.static(join(__dirname, 'public')));
app.listen(8080, (req, res) => console.log("running"))
- data/data.json
{
"titles": {
"index": "this is homepage",
"detail": "this is detailpage"
},
"list": [
{
"id": 1,
"name": "Mike",
"age": 6,
"score": 6
},
{
"id": 2,
"name": "Jodan",
"age": 8,
"score": 8
},
{
"id": 3,
"name": "James",
"age": 10,
"score": 10
}
]
}
- libs/utils.js
// 读取文件
const { readFileSync } = require('fs');
const { resolve } = require('path');
// 读取文件数据
function readFile(path) {
return JSON.parse(readFileSync(resolve(__dirname, path), 'utf8'));
}
module.exports = {
readFile
}
- router/index.js
const { Router } = require('express');
const { indexView, detailView } = require('../controllers');
const router = new Router();
// 页面之间的跳转 index.ejs
router.get('/', indexView);
// 获取详情页面 detail.ejs
router.get('/detail/:id', detailView);
module.exports = router;
- contrillers/index.js
const { getListData, getDetailData } = require('../models');
function indexView(req, res) {
const { title, list } = getListData();
res.render('index', {
title,
list
});
}
function detailView(req, res) {
// params方式获取id
const id = req.params.id;
const { title, student } = getDetailData(id);
res.render('detail', {
title,
student
});
}
module.exports = {
indexView,
detailView
}
- models/index.js
const { readFile } = require('../libs/utils');
// 处理数据的 增删改查
function getListData(req, res) {
const data = readFile('../data/data.json');
const title = data.titles.index;
const list = data.list.map(({id, name}) => ({id, name}));
return {
title,
list
}
}
function getDetailData(id) {
const data = readFile('../data/data.json');
const title = data.titles.detail;
const student = data.list.find(item => item.id == id);
return {
title,
student
}
}
module.exports = {
getListData,
getDetailData
}
views
- views/top.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
- views/bottom.ejs
</body>
</html>
- views/index.ejs
<%- include('top') %>
<div>title: <%= title %></div>
<ul>
<% list.map(({id, name}) => { %>
<li>
<a href="http://localhost:8080/detail/<%= id %>"><%= name %></a>
</li>
<% }) %>
</ul>
<%- include('bottom') %>
- views/detail.ejs
<%- include('top') %>
<div>title: <%= title %></div>
<div>ID: <%= student.id %></div>
<div>Name: <%= student.name %></div>
<div>Age: <%= student.age %></div>
<div>Score: <%= student.score %></div>
<%- include('bottom') %>