本文主要介绍一下前端的基础知识,对比认识一下各个框架的代码编写方式,并介绍我们本次技术选型的主要思路。对于前端三大技术 HTML、CSS、JavaScript,简单的介绍了基本情况和常用语法。中间介绍了现代框架的一些情况,并通过实际的案例,用代码直观的认识一下各种框架的实现方式。最后分析一下项目的技术选型。
本节我们简单介绍一下前端最基础 HTML, CSS, JavaScript 三驾马车。虽然本课程预设的读者为零基础开发者,但是前端开发一定会这三种技术的运用有要求。建议抽空学习一下相关基础。这里仅做语法介绍和基本使用的概览。
开发环境建议使用VS Code 或者 实验楼 提供在线Linux环境,该环境和 VS Code 使用体验基本一致,本文使用在线环境。你可以启动一个终端,并在其中输入 Linux 命令。
后面的命令无特殊说明的都是在此终端命令行中输入。大多数命令可以多开终端窗口分别执行。
那么下面我们就快速的了解一下。
HTML 全称超文本标记语言,几乎是从万维网和浏览器产生伊始就存在的。主要用于结构化信息来方便浏览器展示。以标签对作为主要特征,如 这是一个段落
。这些标签会被浏览器解析成不同的模块,比如 p
标签就是一个段落,img
标签就是一个图片,a
标签就是一个超链接,标签名不区分大小写。
立刻就来尝试一下吧。首先通过命令行新建一个 demo
目录:
mkdir demo
然后命令行进入 demo
目录:
cd ./demo
新建一个 hello.html
文件,可以在实验环境左边的浏览框内在 demo
上右键选择 New File
然后命名为 hello.html
;或者也可在命令行终端输入 touch hello.html
,同样是新建文件。在其中输入以下内容:
<html>
<head>
<meta charset="UTF-8" />
<title>标题title>
head>
<body>
正文
body>
html>
然后右击文件选择 Open With
→ Preview
。或者使用浏览器打开。
看到了吗?其实我们就是新建了一个 .html
后缀的文本文件,然后浏览器就可以将其中的内容展示出来。你也可以在自己的桌面上新建一个,然后使用浏览器打开看看效果。这里嵌套代码的缩进格式是为了美观和可读性,并无严格要求。
head
标签中是一些暂时无需用到的头部信息,渲染的主体是 body
标签。下面我们修改 body
标签里面的内容,填入一些常用标签来直观感受一下。
<body>
<h1>页面标题h1>
<div>一个块容器div>
<div>又一个块容器div>
<p>这里是段落了,间距变大p>
<div>一个块容器div>
<div>
<div>
多层嵌套:
<div>内部第一个div>
<div>内部第二个div>
div>
div>
body>
保存之后切换到浏览标签看一看,有没有感觉被忽悠了?嵌套没嵌套根本没体现出来,就像 Word 里排了一下版,按了几个回车。
因为我们没有对显示样式进行修改,那是 CSS 的事。HTML 主要管内容的组织结构。
这里有一点针对学习的小建议,本课程中给到的全部代码请手动输入,忘记复制和粘贴快捷键。而且最好不要机械的一个字符一个字符照着抄,尽量看过一行或一小段代码之后,靠短暂的印象去输出,别怕出错,只有过脑子并输出实践,才是最快掌握一项技能的捷径。以上两句话是本课程中最有价值内容之一。
下面我们接着修改刚才的代码,再给 body
中添加几个常用标签。每次修改和保存之后记得到预览页看看样式的变化。浏览器要点击F5进行刷新。
<h4>4 级标题h4>
<ul>
<li>
HTML
li>
<li>
CSS
li>
<li>
JavaScript
li>
ul>
<div>
<a href="https://www.shiyanlou.com" target="_blank"
>点击超链接跳转至实验楼首页a
>
div>
<div>
<img
src="https://static.shiyanlou.com/frontend/dist/img/9f43b00.svg"
alt=""
width="200"
/>
div>
最后的链接标签 a
和图片标签 img
出现了标签属性,属性为 attr="value"
格式,可以给标签增加更丰富的信息。
同时 img
标签还是一个单标签,不需要在后面添加 配合使用。
至此对 HTML 的简要介绍告一段落。
互联网上看到的各种五彩缤纷网页都是由这些 HTML 组成的,但是为什么我们写的这么难看?下一节我们就要学习一下如何用 CSS 美化页面。
CSS 全称层叠样式表,是专门用来修饰 HTML 样式的一种语言。我们修改一下上节的 hello.html
文件来直观感受一下。
在 head
标签内部增加以下 style
代码块:
<head>
<meta charset="UTF-8" />
<title>标题title>
<style type="text/css">
div {
border: 1px solid blue;
padding: 2px;
margin: 10px;
}
style>
head>
这是再切换到预览页,发现没那么平铺直叙了。
这就是 CSS 的第一种引入方式,HTML 内置代码块。
大括号外面的 div
是标签选择器,这里选中了本页面中的所有 div
元素。大括号里面是属性名与赋值,属性名都是固定的关键字,并已规定好了值的类型和可选范围。
读代码也就大概知道了,我们将 div
的边框设置为 1 像素宽、固体(单线型)、蓝色,填充(内边距)2 像素,边缘空白(外边距)10 像素。现在可以练习调整一下各个数字,预览看看发生了什么?
再说点题外话,懂一些英文对程序员来说非常必要,除了可以凭感觉就读懂没学过的代码,还可以在面向 Google 编程、面向 Stack Overflow 编程、面向 Github Issues 编程时游刃有余。
然后我们再试一下外部文件引入,在 hello.html
的同级目录新建 hello.css
,输入以下内容保存:
div {
color: green;
border: 2px dotted red;
}
然后修改 hello.html
,在 style
标签后面增加一行 link
标签,添加引入类型和地址:
<style type="text/css">
div {
border: 1px solid blue;
padding: 2px;
margin: 10px;
}
style>
<link rel="stylesheet" href="hello.css" />
预览看看,文字颜色变为绿色,边框的样式也被更新为 2 像素宽、点线型红色。
同样是 div
选择器,为什么边框的样式被覆盖了呢?注意 CSS 在同样条件下会后面代码覆盖前面,可以尝试交换 link
标签和 style
标签块的顺序看看。
最后一种叫行间样式,这个结构更简单。修改 hello.html
中的
为
<div style="margin: 60px 0 10px 30px ;color:purple;">内部第一个div>
样式覆盖前两种方式了,因为行间样式的优先级较高。这里涉及到选择器权重,先给一个简单公式了解一下。
!important > 行间样式 > ID > class | 伪类 | 属性选择 > 标签 > 继承 | 通配符
。
多个选择器作用时权重相加。这里算 CSS 里有点复杂的部分,暂时不展开。
这里还有个小知识点是内外边距 margin
和 padding
接受的完整的值是四个,顺序固定为“上 右 下 左”。如果省略参数则从末尾计算对向合并。比如:
margin:40px 20px 50px;
三个参数时,左右同为 20px。
margin:40px 20px;
两个参数时 上下同为 40px, 左右同为 20px。
margin:40px;
一个参数时呢?请自行尝试理解。
CSS 先讲这么多,虽然没有把我们的页面变多好看,但最起码知道努力的方向了。
制作 JavaScript 的快速入门简直非常伤脑筋。比起前两种技术 HTML 和 CSS,这是货真价实的编程语言了。也是我们后面要用到的 Vue.js 和 Node.js 中的根基,一下子又很难讲很多,所以还是希望同学们能重视起来系统学习一下,最起码读到后面的代码时不至于陷入“这是啥这又是啥”的窘境。
来段代码直观认知一下,还是先内部代码块引入。
在 hello.html
的 head
标签内增加一个代码块:
<link rel="stylesheet" href="./hello.css">
<script>
let message = "字符串提示";
function showMSG(msg) {
alert(msg);
}
</script>
修改 hello.html
的 h1
标签为:
<h1 onclick="showMSG(message)">页面标题h1>
保存预览,点击“页面标题”,会弹出提示框。
JavaScript 代码加载之后就会执行,不存在编译阶段。行末的分号绝大多数时候可以省略。
我们先定义了一个变量 message
,并赋值为“字符串提示”。定义变量关键字原是 var,ES6 新增关键字 let 有更清晰的作用域,可替代使用。
学习 JavaScript 经常会碰到 ES6、ES7 之类的名词,实际上是 ECMAScript 标准的版本号的意思。可以简单理解为新版标准为 JavaScript 添加特定新特性。
然后我们定义了一个函数 showMSG
,并添加一个形参 msg
。在函数体内部调用浏览器弹框方法,显示 msg
的值。function
是定义函数的关键字,暂时先把它当做一个功能封闭的盒子,当函数调用时,执行函数体内的代码。
调用部分是先给 h1
标签添加了 onclick
点击事件,被点击时触发 showMSG(message)
,也就是把 message
传给了 msg
。
之后再试一下调用外部 js 文件,新建 demo.js
文件,写入下面内容并保存。
message = "修改一下字符串";
然后修改 hello.html
文件,在 script
代码块后面增加一行:
<script src="./demo.js">script>
这次保存预览,点击“页面标题”,可以看到弹窗的文字变了。这个演示了 script
代码块在页面可以同时存在多个,也是顺序调用,而且互相之间可以直接访问。文件命名也没有要求,希望不会逼死强迫症。
JavaScript 就是为什么网页可以做那么多交互的源头了。掌握起来任重道远。
截止 2019 年底,前端三大主流框架为 VAR(Vue.js, Angular, React)应该是没有悬念的,基本终结了前些年 jQuery 一统天下的局面。
从我个人角度简单评价一下:
jQuery 有方便的选择器操作和万能的 DOM 操作。
三大框架无论哪一个都具有组件化,数据绑定,高性能,丰富的语法糖等优点,选哪一个深入下去都可以做的非常好。
名称 | 开发维护者 | 特点 | 热度 | 适用范围 | 学习难度 |
---|---|---|---|---|---|
Angular | 强制 TS,工程化 | 中 | 大型项目 | 高 | |
React | JSX 语法,生态最繁荣,资源最丰富 | 最高 | 所有项目 | 中 | |
Vue.js | 尤雨溪及社区 | 模板语法,国内生态繁荣、资源丰富 | 高 | 所有项目 | 低 |
这里为了更直观的了解一下这些技术,我专门制作了一组演示实例,用原生 JS, jQuery, React, Vue.js 分别实现一下。为什么没有 Angular 呢?官方只推荐 TypeScript 和 Node.js 去实现,难以在本案例下简单对比,就先把它看做更严格更复杂更庞大的 Vue.js 好了。
案例只实现一个最简单的功能,通过数组渲染一组无序列表,然后通过输入框和按钮给数组增加元素,然后重新渲染整个数组。还是老建议,除了地址引用复制,其他尽量手敲,用身体感受不同框架下代码的差异。
在路径 /home/projest/demo
路径下新建 js.html
文件。输入以下内容:
<html>
<head>
<meta charset="UTF-8" />
<title>JavaScript Demotitle>
head>
<body>
<h2>JavaScript Demoh2>
<div>
<input type="text" id="input" />
<button onclick="changeList()">添加button>
<ul id="list">ul>
div>
<script>
let items = ["Vue.js", "Angular", "React", "jQuery"];
function appendText(value) {
var para = document.createElement("li");
var node = document.createTextNode(value);
para.appendChild(node);
var list = document.getElementById("list");
list.appendChild(para);
}
function clearList() {
let list = document.getElementById("list");
var listChildren = list.childNodes;
for (let index = listChildren.length - 1; index >= 0; index--) {
const element = listChildren[index];
list.removeChild(element);
}
}
function refreshList() {
clearList();
for (let index = 0; index < items.length; index++) {
const element = items[index];
appendText(element);
}
}
function changeList() {
let newItem = document.getElementById("input").value;
items.push(newItem);
refreshList();
}
refreshList();
script>
body>
html>
保存之后预览一下。尝试在输入框写入内容,然后点击添加按钮。
原生的代码比较直白。先定义了 items
数组并赋初始值。然后定义了新增节点、清空所有节点、重新渲染所有节点和按钮触发修改这四个函数。最后一行为初始化后执行第一次列表渲染。
这里用到了很多 DOM 操作,通过 id
拿到元素,再用 DOM 语法去增加或者删除。所以最好提前给 HTML 元素加好 id
方便获取。这段代码应该是很清晰好读的,不多做解释了。
再来一个小提示,编写函数时每个函数包含功能要尽可能少,但是命名一定要清晰有意义不怕长。好的编程习惯会让你事半功倍。
下面我们看看神器 jQuery 的表现。
在路径 /home/projest/demo
路径下新建 jquery.html
文件。输入以下内容:
<html>
<head>
<meta charset="UTF-8" />
<title>jQuery Demotitle>
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js">script>
head>
<body>
<h2>jQuery Demoh2>
<div>
<input type="text" />
<button>添加button>
<ul>ul>
div>
<script>
let items = ["Vue.js", "Angular", "React", "jQuery"];
function appendText(value) {
var txt = $("").text(value);
$("ul").append(txt);
}
function refreshList() {
$("ul").empty();
for (let index = 0; index < items.length; index++) {
const element = items[index];
appendText(element);
}
}
$(document).ready(function() {
refreshList();
$("button").click(function(event) {
let newItem = $("input").val();
items.push(newItem);
refreshList();
});
});
script>
body>
html>
第 6 行引入了 jQuery 库。这个代码比之前就轻量多了,首先就是 $
为首的各种选择器简化了选择操作,也基本不用提前定义 id
了,然后封装的 DOM 操作命令简洁又强大。清空子节点不用自己写了,事件也可以在脚本里很方便的添加。
在路径 /home/projest/demo
路径下新建 react.html
文件。输入以下内容:
<html>
<head>
<meta charset="UTF-8" />
<title>React Demotitle>
<script src="https://unpkg.com/react@16/umd/react.development.js">script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js">script>
<script src="https://unpkg.com/[email protected]/babel.min.js">script>
head>
<body>
<h2>React Demoh2>
<div id="root">div>
<script type="text/babel">
class Welcome extends React.Component {
constructor(props) {
super(props);
const list = props.list;
const listItems = list.map((item, index) => (
<li key={index}>{item}</li>
));
this.state = { listItems, newItem: "" };
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleClick() {
this.setState(prevState => ({
listItems: [
...prevState.listItems,
<li key={prevState.listItems.length}>{prevState.newItem}</li>
]
}));
}
handleChange() {
this.setState({ newItem: event.target.value });
}
render() {
return (
<div>
<input
type="text"
value={this.state.newItem}
onChange={this.handleChange}
/>
<button onClick={this.handleClick}>添加</button>
<ul>{this.state.listItems}</ul>
</div>
);
}
}
const items = ["Vue.js", "Angular", "React", "Jquery"];
ReactDOM.render(
<Welcome list={items} />,
document.getElementById("root")
);
script>
body>
html>
到了 React 风格突变,首先就是用到了 JavaScript 语句里写标签的 return()
这种 JSX 写法,注意括号里不是字符串哦。先是创建了一个组件类,在构造函数里增加了 state
并根据传入的 props
赋值。两个函数分别是更新列表和更新输入值,其中有一个 ...
是数组展开运算符(ES6)。后面 render()
的返回值为渲染模板。
如果说以前的网页是标签中夹杂着脚本,React 就像是脚本中夹杂着标签。通过这种结构可以轻松的写出可复用的组件,只要传入不同的数据即可。
终于来到我的最爱了。
在路径 /home/projest/demo
路径下新建 vue.html
文件。输入以下内容:
<html>
<head>
<meta charset="UTF-8" />
<title>Vue.js Demotitle>
<script src="https://cdn.jsdelivr.net/npm/[email protected]">script>
head>
<body>
<div id="root">
<h2>Vue.js Demoh2>
<input v-model="newItem" type="text" />
<button @click="items.push(newItem)">添加button>
<ul>
<li v-for="item in items" :key="item.id">
{{ item }}
li>
ul>
div>
<script>
new Vue({
el: "#root",
data: {
items: ["Vue.js", "Angular", "React", "jQuery"],
newItem: ""
}
});
script>
body>
html>
在标签里加了些似曾相识的指令,功能就完成了。构思这个例子之前我也没觉得能对比出什么,就是直观的看一下各种框架的代码结构和外貌。可 Vue.js 确实体现出了低门槛和易用性,也许和创始人——前谷歌工程师尤雨溪后来居上地汲取了 Angular 和 React 两家的优点有关系。
因为后面还有详细的介绍,所以这里不解释语法了。
还有 Vue.js 中文文档完整,国内的相关资源丰富,这都是非常奢侈难得的优势。2020 年 Vue.js 即将推出新版本 3.0,会在兼容 2.0 的基础上增加一些更新更好的特性,正是入手学习的好时机。
服务器后端的选择太多了,JAVA 应该还是老大没有悬念,PHP, C#, Go, Node.js, Python 也各有千秋。还是那句老话,技术都没什么大问题,主要的问题是技术不够精。前端做全栈推荐 Node.js 不纠结了,一种语言和生态了解和熟悉到极致比什么都强。尤其是 TypeScript 上马之后,有了静态类型大型项目也不慌。
确定 Node.js 之后,选择就简单多了。Express, Koa 和 Egg.js 几乎是一脉相承,Express 是 Node.js 生态广泛使用 Web 框架,网上很多教程和资源都是它的。Koa 就是 Express 团队吸收了很多新特性的下一代,2.0 版本以后除了 ES6 特性还增加了 Promise, async/await 解决回调地狱。Egg.js 是阿里巴巴基于 Koa2 的扩展封装。还有一些其他 Web 框架流行度和受众没那么高,暂不考虑了。
这里我的选择偏保守,还是使用 Koa。Express 就不推荐再用了——毕竟官方重构最为致命,Egg.js 新手入手又稍显复杂,如果真有需求可以在学通 Koa 以后再去考虑。
Koa2 还有个好玩的地方是库很小,只保留核心功能。需增加功能时再添加各种官方或者第三方中间件,多数中间件只做一件事,结构清晰源码好读,非常适合学习和练手。
开源数据库 MySQL, PostgreSQL, MongoDB 都非常流行,小项目大项目都可以应付下来。Node.js 生态对各种数据库支持也都不错。但是 MongoDB 作为存储键值对 NoSQL 数据库,数据文档本身就是以 JSON(JavaScript Object Notation) 的格式设计存在的,与 JavaScript 天然自洽。本身又是轻量好部署,扩展性强。所以直接选择 MongoDB。
如果自身对 SQL 语言有过学习和使用的经验,也可以考虑继续使用关系型数据库,或再配上如 Sequelize 这样的 ORM 类库,数据库使用并不是问题。
主流有 Apache, Nginx, tomcat, IIS 等。我们选一个轻量、简单、跨平台、性能高的,Nginx 完全搞定,在线环境有预装,自己安装使用较方便,也只要写好配置就能,不用犹豫。
本实验中我们快速了解了一下前端基础知识,并以实际代码实现来感受了一下前端框架的异同。
最后我们确定的技术路线是
本课程的后续地址在:《Vue.js 和 Node.js 构建内容发布系统》,
https://www.shiyanlou.com/courses/1505。欢迎点击了解课程介绍和目录。
通过邀请码: 2Y4iA1cu 购买可享 9 折优惠。前 100 名使用邀请码购买还可以获得 10 元现金红包。
实际上并不存在什么最好的技术路线,只有最适合某个项目的,个人或团队最熟悉的技术路线。新技术发展日新月异,希望在学习过程中带给你的心得与成就感能长远的帮助到你,持续学习保持进步。