网站交互方式
-
经典的多页面
- 前后端耦合,开发和维护效率低下
- 用户体验一般,点击刷新跳转,等待时间过长
- 每个页面都需要重新加载渲染,速度慢
- 有利于 SEO 搜索引擎搜索(蜘蛛会爬链接)
- 应用场景:京东商城
-
现代式的单页面(Single Page Application,简称 SPA)
- 开发方式好,前后端分离,开发效率高,可维护性好
- 服务端不关心页面,只处理数据
- 客户端不关心数据库和数据操作,只关心通过接口拿数据和服务端交互,处理页面
- 两者通过接口来交互
- 交互用户体验好,就像一个原生的客户端软件一样使用
- 只需要加载渲染局部视图即可,不需要整页刷新
- 单页面应用开发技术复杂,所以诞生了一堆开发框架:
- AngularJS
- ReactJS
- VueJS
- 单页面技术虽然已经很成熟了,但是都无法兼容低版本浏览器,大部分都是 ie9 以上
- 现在除了一些电商网站,已经很少有系统需要去兼容低版本浏览器
- 单页面由于数据都是异步加载进来的,所以不会被搜索引擎搜索到,不利于 SEO
- 应用场景:网易云音乐
- 开发方式好,前后端分离,开发效率高,可维护性好
模拟前后端分离开发模式
前后端分离 - 客户端多页开发
下面构建一个简单的 todo list 来展现多页
后台
后台只需要设计好以下数据接口,让前端可以访问
Get:http://127.0.0.1:3000/todos
Post:http://127.0.0.1:3000/todos
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
const todos = [{
id:1,
title:'吃饭'
},
{
id:2,
title:'睡觉'
},
{
id:3,
title:'学习'
}
]
app
.get('/todos', (req, res) => {
res.json(todos)
})
.post('/todos', (req, res) => {
const todo = {
title: req.body.title,
id: todos[todos.length-1].id + 1
}
todos.push(todo)
res.json(todos)
})
app.listen(3000, () => console.log('api server running 3000'))


前端
前端直接使用 ajax 异步请求后台的接口请求数据后渲染页面
index.html (渲染 todo list)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="header">头部</div>
<div class="aside">侧边栏</div>
<a href="todo/add.html">添加 todo</a>
<ul id="container"></ul>
<script id="tpl" type="text/template">
{{ each todos }}
<li>{{ $value.title }}</li>
{{ /each}}
</script>
<script src="node_modules/jquery/dist/jquery.js"></script>
<script src="node_modules/art-template/lib/template-web.js"></script>
<script>
$.get('http://127.0.0.1:3000/todos',(data) => {
var htmlStr = template('tpl',{
todos:data
})
$('#container').html(htmlStr)
})
</script>
</body>
</html>
add.html (输入 todo 点击保存后跳转 index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="header">头部</div>
<div class="aside">侧边栏</div>
<form action="" id="add_form">
<div>
<label for="title">todo</label>
<input type="text" name="title" id="title">
</div>
<div>
<input type="submit" value="保存">
</div>
</form>
<script src="../node_modules/jquery/dist/jquery.js"></script>
<script>
$('#add_form').on('submit', function(e) {
e.preventDefault()
$.post('http://127.0.0.1:3000/todos', $(this).serialize(), function (data) {
window.location.href = '/'
})
})
</script>
</body>
</html>
上述例子可以看出来前端后台职责明确,但多页需要整个页面重新渲染
前后端分离 - 客户端单页开发
单页开发可以通过增加 hash 进行页面标识(类似锚点),通过window.onhashchange
事件判断 hash 值改变,进而通过window.location.hash
获取 hash 值渲染对应的局部页面。(本案例服务端接口同前)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="header">头部</div>
<div class="aside">
<li><a href="#/">我的todo list</a></li>
<li><a href="#/add">添加todo list</a></li>
</div>
<div id="container"></div>
<script src="node_modules/jquery/dist/jquery.js"></script>
<script src="node_modules/art-template/lib/template-web.js"></script>
<script>
window.onhashchange = function () {
var hash = window.location.hash.substr(1)
if (hash === '/') {
$.get('./myTodoList.html', function (data) {
$('#container').html(data)
})
} else if (hash === '/add) {
$.get('./add.html', function (data) {
$('#container').html(data)
})
}
}
</script>
</body>
</html>
myTodoList.html
<div>
<hr>
我的 todo list:
<ul id="todos-container"></ul>
</div>
<script id="tpl-todos" type="text/template">
{{ each todos }}
<li>{{ $value.title }}</li>
{{ /each }}
</script>
<script>
$.get('http://127.0.0.1:3000/todos', function (data) {
var htmlStr = template('tpl-todos', {
todos: data
})
$('#todos-container').html(htmlStr)
})
</script>
add.html
<form action="" id="add_form">
<div>
<label for="title">todo</label>
<input type="text" name="title" id="title">
</div>
<div>
<input type="submit" value="保存">
</div>
</form>
<script>
$('#add_form').on('submit', function(e) {
e.preventDefault()
$.post('http://127.0.0.1:3000/todos', $(this).serialize(), function (data) {
window.location.href = '/'
})
})
</script>
通过上述方式可以实现单页,但是这种方式有缺陷,在操作 DOM 元素进行渲染的过程中,不同页面的 DOM 元素很可能冲突,一旦页面多了同样难以维护,因此诞生了三大前端框架:
- angular
- 2009 年诞生
- 目的:为了便于开发单页应用程序
- 但最主要的是为前端带来了 MVVM 的开发模式,这种开发方式是数据驱动视图,不操作 DOM
- react
- Facebook 公司开发的 Web 框架
- 组件化
- vue
- Vue 作者:尤雨溪
- Vue 借鉴了 angular 和 React 之所长,是后起之秀
- 最大程度解放了 DOM 的操作
网友评论