Vue
前端
- web里的网页里 有 三门基础的语言 HTML CSS JavaScript/js
- HTML用于定义网页的基本内容
- CSS样式用于调整网页内容的样式(外观相关的)
- js 用于给网页内容 添加 功能
HTML
HTML(超文本标记语言)是一种用于创建网页标记语言。HTML使用标签来定义网页中的元素,如标题、段落、链接、图像等。它是一种静态语言,主要负责网页的结构和语义化。
网页基本信息
<!-- DOCTYPE 文本类型,告诉浏览器使用的是什么规范-->
<!DOCTYPE html>
<html lang="en">
<!-- head 网页头部 -->
<head>
<!-- meta 描述性标签,可描述一些网站信息:比如编码、关键字、间接叙述-->
<meta charset="UTF-8">
<meta name="keywords" content="前端开始">
<meta name="description" content="这是三件套的开始">
<!-- title 打开网站后看到的网站名称 -->
<title>First HTML</title>
</head>
<!-- 主体 内部是可在网页页面上显示的内容-->
<body>
Hello,HTML
</body>
</html>
基本标签
<!--标题标签-->
<h1>复习前端</h1>
<h2>复习前端</h2>
<h6>复习前端</h6>
<!--段落标签,每个标签自成一段-->
<p>复习前端</p>
<p>复习前端</p>
<!--换行标签,只是换行,多行成一段-->
复习前端<br>
复习前端<br>
<!--水平线标签-->
<hr>
<hr>
<!--字体样式标签-->
粗体:<strong>复习前端</strong>
斜体:<em>复习前端</em>
<!--特殊格式-->
空 格
块级标签,简称块:默认在页面布局里,自己独占一行。
CSS盒子模型属性里的 宽高,内填充,外边框,边框 都可以单独控制且有效果
常用的块级元素有 h1~h6 p ul li ol table form div…
行级标签/元素:默认的在页面布局里,自己会跟其他行级标签挤在一行,除非这一行挤不下,才会换行
- CSS盒子模型属性里的 宽高,内填充,外边框,边框 有一部分是可以控制且有效果的
- 常用的行级元素有 a b span font img input select label…
特殊标签
<!--1.图片标签-->
<img src="../resources/image/图片一.jpg" alt="风景" content="落日" title="前端复习">
alt图片加载失败时显式的文字,title鼠标悬停到图片显示的文字
<!--2.链接标签-->
<a href="HelloHTML.html" target="_blank">点击跳转,文字跳转</a>
<a href="HelloHTML.html">
<img src="../resources/image/图片二.jpg" alt="风景" title="前端复习" height="300" width="300">
</a>
<!--锚链接,定义一个锚标记,然后跳转到锚标记-->
<a href="top">顶部</a>
<a href="#top">回到顶部</a>
<!--邮件链接-->
<a href="mailto:2869861273@qq.com">点击发送邮件</a>
</body>
<!--3.列表标签-->
<!--有序列表-->
<ol>
<li>前端复习1</li>
<li>前端复习2</li>
<li>前端复习3</li>
</ol>
<!--无序列表,不是顺序杂乱,而是没有序号标明顺序-->
<ul>
<li>前端复习1</li>
<li>前端复习2</li>
<li>前端复习3</li>
</ul>
<!--自定义列表,dt标题,dd内容-->
<dl>
<dt>前端复习</dt>
<dd>前端复习1</dd>
<dd>前端复习1</dd>
<dd>前端复习1</dd>
</dl>
<!--4.表格标签,tr表格里的行,td表格里的列-->
table 表格 默认不显示边框 border属性可以调整边框
th 表头单元格 比普通单元格 多了 加粗字体,默认居中
<table border="1px">
<tr>
<!-- 跨列合并,保留最左单元格,添加属性 colspan -->
<td colspan="3">1</td>
</tr>
<tr>
<!-- 跨行合并,保留最上单元格,添加属性 rowspan -->
<td rowspan="2">复习</td>
<td>前端复习</td>
<td>前端复习</td>
<!-- 当设置了跨行和跨列时,后面所被影响的表格需要去掉从而对齐 -->
</tr>
<tr>
<td>前端复习</td>
<td>前端复习</td>
</tr>
<!--5.音视频标签,controls显示进度条 autoplay设置自动播放-->
<video src="" controls autoplay></video>
<audio src="" controls autoplay></audio>
<!--6.iframe内联标签,即在一个网页里还有一个内联框,内联框里是另一个网址-->
<iframe src="https://www.baidu.com" frameborder="0" width="500" height="500"></iframe>
</table>
form表单
- 表单是用来收集用户的不同输入的数据,然后发送给”服务器程序”
- 表单form标签,内部可以定义很多不同形式的”表单组件”.
- 表单组件有的表现为单行文本框,密码框,按钮,复选框,下拉菜单
- form标签有method属性,设置 本表单的提交方式,默认值为get 可以设置为post
- form标签有action属性,设置 本表单提交到的路径,通常是”服务器程序”的路径
- form标签有enctype属性,设置 当表单里有文件上传时,表单的特殊编码形式
<!--7.表单 -->
<form action="HelloHTML.html" method="get" enctype="multipart/form-data">
<!-- name的值就是提交的时候的键 组件里用户输入的数据,就是提交的时候 键对应的值 -->
<!-- value 可以设置默认值 -->
<!-- placeholder 占位符,不输入的时候一个提示 -->
<!-- size 输入框的长度 -->
<!-- maxlength 能输入的字符的最大个数 -->
<!-- required 表示必须填写,否则表单无法提交,属性名和值相同的,这样的属性 可以直接写属性 -->
<!-- pattern 设置 正则表达式 -->
<!-- 提交按钮 HTML中已经定义好的 可以提交表单的按钮,把表单里的数据发送出去 -->
<input type="text" name="username" placeholder="输入用户名" value="name" size="30"
required="required" pattern="^[a-zA-Z]\w{3,7}$" >
<!-- 单选按钮 必须提供相同的name属性 才能成为互斥的一组
<label>Gender:</label>
<input type="radio" name="gender" value="1" checked/><label>Female</label><img src="img/logo.png"/>
<input type="radio" name="gender" value="2"/><label>Male</label><img src="img/logo.png"/>
<br/>
input 单标签 它的值需要使用value来定义.后面的label/文本/图片 仅仅和它是排版上一起
单选按钮 默认选择的属性 checked -->
<!-- 图片形式的提交按钮 -->
<input type="image" src="img/logo.png" width="50px" height="50px"/>
<input type="button" value="普通按钮"/> <!-- js添加功能 -->
<!-- 按钮这里 还有一个特殊的button双标签 根据type属性的不同 有不同的效果 -->
<br/>
<button type="button">普通按钮</button>
<button type="submit">提交按钮:有功能</button>
<button type="reset">重置按钮:有功能</button>
<!--单选框 name表示组,只有在同一组的才能选择其一 -->
男<input type="radio" value="girl" name="sex">
女<input type="radio" value="boy" name="sex">
<!--多选框 checked默认选中 -->
<p>爱好:
游戏<input type="checkbox" value="play" name="hobby" checked>
舞蹈<input type="checkbox" value="dance" name="hobby">
吃<input type="checkbox" value="eat" name="hobby">
</p>
<input type="hidden" name="secret" value="秘密数据"/>
<!-- 隐藏域 用户看不到,但是可以跟随表单一起提交的数据,一般是程序员设置在此的一个数据 -->
<label for="birthdayInput">Birthday:</label>
<!-- 日期,邮件等 -->
<input type="date" name="birthday" id="birthdayInput">
<br/>
<label for="emailInput">Email:</label>
<input type="email" name="email" id="emailInput" required/>
<br/>
<input type="color" name="color">
<input type="week" name="week">
<input type="time" name="time">
<!-- 有文件上传时,必须将form的enctype 属性 改为enctype="multipart/form-data"(多组件表单数据)
并且 method 必须改为post,这里没有改 因为 并不能进行真正的上传
-->
<label for="photoChoose">Photo:</label>
<input type="file" name="photo" id="photoChoose"/>
<br/>
<!--8.下拉框 selected默认选择-->
<p>下拉框:
<select name="列表名称" >
<option value="china" selected disabled>中国</option>
<option value="us">英国</option>
<option value="ufo">美国</option>
</select>
</p>
<!--9.文本域,cols,rows行列长度-->
<p>文本域:
<textarea name="textarea" cols="30" rows="10">文本框</textarea>
</p>
</form>
CSS
CSS(层叠样式表)是一种用于描述网页样式和布局的样式表语言。它与HTML配合使用,负责网页的外观和样式。通过使用CSS,可以控制元素的大小、颜色、字体、布局,实现网页的美观效果和排版。
导入方式
<!-- 1.内部样式-->
<style>
h1{
color: red;
}
</style>
<!-- 2.外部样式:链接外部样式表是指通过HTML的link链接标签,建立样式文件和网页的关联。-->
<head>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<!-- 3.行内样式-->
<h1 color="green">Hello</h1>
<p style="color:red; font-size:30px; font-family:黑体;">
</body>
基本选择器
<!-- 1.标签选择器,选择所有同一标签 -->
<style type="text/css">
标签名 {
属性1:属性值1;
属性2:属性值2;
}
h1 {
color: red;
}
</style>
<!-- 2.类选择器,需先在标签里定义一个任意类属性,可多个标签定义同一个类名,然后在css中.类名-->
<style>
.类名 {
属性1:属性值1;
}
.liy{
color: red;
}
</style>
<!-- 使用类样式 -->
<标签名 class="类名"> 标签内容 </标签名>
<h1 class="liy">类选择器</h1>
<h2 class="liy">类选择器</h2>
<!-- 3.id选择器,同样先定义一个id,再在css中#id选择,但一个id只能定义一个标签 -->
<style type="text/css">
#ID标识名 {
属性1:属性值1;
属性2:属性值2;
}
#gu{
color: red;
}
</style>
<h1 id="gu">id选择器</h1>
<!-- 4.通配符选择器,查找页面所有标签,设置相同样式 -->
* {
color: red;
}
高级选择器
<style>
body p{ 选中的是body下面的所有p标签 -- 后代选择器
background: red;
}
</style>
<style>
body > p{ 选中的是body下面的一代p标签 -- 子代选择器
background: red;
}
</style>
<style>
p,.red,#header { 组合(并集)选择器,逗号分隔
color:red;
font-size:12px;
}
</style>
<style>
.active+p { 选的是active标签之后的一个p标签 -- 相邻兄弟选择器
background: red;
}
</style>
<style>
.active~p { 选的是激活标签之后的所有p类型标签
background: red;
}
</style>
<style>
/* :hover 鼠标悬浮时 :active 鼠标点击但未松开时 :focus 获取光标焦点时*/
h1:hover,p:hover{ 伪类选择器:伪类表示元素状态,选中元素的某个状态设置样式。
background-color: azure;
}
h1:active{
color: cornflowerblue;
}
/* :first-child 选择作为第一个子元素的 */
tr:first-child:hover{
background-color: aquamarine;
}
/*
这里是对tr进行 筛选, 选出所有tr中 作为别人的第一个子元素的tr
并不是选取 tr内部的第一个孩子
*/
</style>
属性选择器
/* 首先搭建标签并设置标签的格式 */
<p class="demo">
<a href="www.baidu.com" class="links item first" id="first">1</a>
<a href="" class="links item active" target="_blank" title="test">2</a>
<a href="resources/image/图片一.jpg" class="links item" >3</a>
<a href="abc" class="links item">4</a>
<a href="/a.pdf" class="links item">5</a>
<a href="/abc.pdf" class="links item">6</a>
<a href="abcd.docx" class="links item">7</a>
<a href="abc.docx" class="links item">8</a>
</p>
<style>
.demo a{
float: left;
display: block;
height: 50px;
width: 50px;
border-radius: 10px;
background: #2700ff;
text-align: center;
color: gainsboro;
text-decoration: none;
margin-right: 5px;
font: bold 20px/50px Arial;
}
</style>
/* 在style中进行选择,属性选择器格式就是标签+[属性] */
/* 1.选择存在id的元素*/
a[id] {
background: red;
}
/* 2.选择id为first的标签*/
a[id="first"] {
color: black;
}
/* 3.选中class里有links的标签*/
a[class*="links"] {
background: bisque;
}
/* 4.特定的开头和结尾 */
a[href^=w] {
background: cornflowerblue;
}
a[href$=x] {
background: red;
}
文字控制
p{
font-family: 华文行楷; /* 字体类型 */
font-size: 16px; /* 字体大小 */
font-style: oblique; /* 字体样式:italic斜体字,oblique倾斜的文字 */
font-weight: 900; /* 字体粗细 */
}
span{
font-size: 2rem;
line-height:25px; /* 设置行高(即行间距),常用取值为 25px、28px */
/* 设置元素中文本的水平对齐方式,继承给子级 */
text-align: right;
}
<style type="text/css">
#p1 {
text-indent: 2em;
}
#p1 > a {
text-decoration: none; /* 设置文本修饰, 常用的取值为underline(下划线)、none */
color: green;
font-weight: bold;
}
#p1 > a:hover {
text-decoration: underline;
color: gold;
background-color: green;
}
.pp2 {
text-transform: capitalize;
word-spacing: 2em;
text-align: center; /* 设置对齐方式,常用的取值为left、right 以及 center */
}
.pp3 {
letter-spacing: 1em; /* 设置字符间距,常用的取值为3px、8px */
}
ul {
/*list-style-position: inside;*/
/*list-style-type: decimal;*/
/*list-style-type: none;*/
/*list-style-image: url("img/logo.png");*/
/* 列表在设置时,一般会直接把列表项标志设置为none */
}
table {
border-collapse: collapse;
/*border-spacing: 10px 15px;*/
/*caption-side: bottom;*/
/* empty-cells: hide;*/
/* 列宽度算法 */
/*table-layout: fixed;*/
}
button{
font-size: 100px;
/*background-color: transparent;*//* 透明 */
}
button:hover{
/*outline-style: solid;
outline-width: 2px;
outline-color: red;*/
outline: green double 3px;
}
</style>
CSS特性
CSS特性:化简代码 / 定位问题,并解决问题
- 继承性:子级默认继承父级的文字控制属性。 如果标签有默认文字样式会继承失败。
- 层叠性:相同属性后面的覆盖前面的,不同属性叠加。
- 优先级:当一个标签使用了多种选择器时,基于不同种类的选择器的匹配规则。
基础选择器
规则:选择器优先级高的样式生效。
公式:通配符选择器 < 标签选择器 < 类选择器 < id选择器 < 行内样式 < !important
(选中标签的范围越大,优先级越低)
复合选择器-叠加
叠加计算:如果是复合选择器,则需要权重叠加计算。
公式:(每一级之间不存在进位)

规则:
- 从左向右依次比较选个数,同一级个数多的优先级高,如果个数相同,则向后比较
- !important 权重最高
- 继承权重最低
显示设置
display 用于设置行内元素的排列。display方向不可以控制。
float浮动起来的话会脱离标准文档流,所以要解决父级边框塌陷的问题
display: block; /* 块级 */
display: inline-block; /* 行内块 一行可以显示多个 */
display: inline; /* 行内 */
float: left; /* 独立于底层,设置浮动 */
float: right;
clear: right; /* 右侧不允许有浮动元素 */
clear: both; /* 两侧都不允许有浮动元素 */
clear: right;
clear: none;
#d1{
width: 200px;
height: 200px;
border: 2px solid dimgray;
/* overflow 调整内容溢出 */
/*overflow: hidden; *//*隐藏 */
/*overflow: scroll;*//* 滚动条*/
overflow: auto;/* 自动添加滚动条 */
}
盒子模型:即边距margin,边框border,填充padding,和实际内容。
外边距设置居中:margin: auto;(前提该标签需要在一个块元素内,即要有边界)
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
.div01{
width: 200px;/* width,height仅仅设置内容区域 */
height: 200px;
padding: 2em 4em;/* padding是简写,简写了四个方向 */
/* 如果是给1个值 那就是 4个方向都设置 */
/* 如果给2个值 第一个值是 上下 第二个值是 左右 */
/* 如果给3个值 第一个值是 上 第二个值 左右 第三个值 下 */
/* 如果给4个值 分别是 上 右 下 左 顺时针 */
border: 2px solid red;
}
span{
width: 200px;
height: 200px;
/* 行级元素的 宽高属性 无效,根据内容的大小自动调整的 */
}
#span2{
/*border: 10px solid red;*//* 边框可以调整左右,上下不建议调整 */
/*padding: 20px;*//* 内填充可以调整左右,上下不建议调整 */
/*margin: 20px;*//* 外边距可以调整左右,上下不建议调整 */
display: block;
width: 200px;
height: 200px;
border: 2px solid purple;
}
.div01:first-child{
border:2px solid blue;
margin:20px;
/* padding margin border 都可以写 xxx-方向 */
}
</style>
</head>
<body>
<!-- div 块级标签 没有任何显示效果,需要结合css盒子模型属性的调整 -->
<div class="div01" style="display: none">
这是内容!
</div>
<div class="div01" style="display: inline">
这是内容!
</div>
<!-- 盒子模型/框模型 在 行级元素里的部分 不建议调整 -->
<span id="span1">span1</span><span id="span2">span2</span><span id="span3">span3</span>
</body>
定位
文档流:默认的摆放形式,行级和行级在一行,实在放不下就换行,块级独占一行
- 相对定位relative:相对于 自身加载的原始位置 的 定位 原来的位置是被保留的
- 绝对定位absolute:相对于 已经定位的父元素 的 定位 原来的位置不被保留.
- 固定定位fixed:相对于 视窗(浏览器窗口) 原来的位置不被保留.
#move{
width: 400px;
height: 200px;
background-color: gold;
/* 固定定位 */
position: fixed;
top: 200px;
left: 400px;
z-index: -1;
}
#outer{
width: 200px;
height: 200px;
background-color: blue;
position: relative;/* 相对定位 */
left: 100px; /* 定位之后的位置 左边 100px 是原来的位置 */
top: 100px; /* 定位之后的位置 上边100px 是原来的位置 */
z-index: -1;
}
#outer2{
width: 200px;
height: 200px;
background-color: aquamarine;
position: absolute;/* 绝对定位 父亲是body */
left: 200px;
top: 100px;
z-index: -2;
}
JavaScript
JavaScript是一种基于对象和事件驱动的脚本语言,作用是给网页添加交互功能和动态效果。它可以操作网页元素、响应用户操作、发送网络请求、处理数据等。JavaScript使得网页具有更高级的交互性和动态性,可以实现表单验证、页面动画、实时数据更新等。
html中使用js有三种,标签内,内部,外部 使用js一般是两种,也就是内部和外部
标签内:
<a href="javascript:alert('这是js的信息弹框!这样的用法几乎不使用')">点我弹出一个信息框</a>
内部:
<head>
...
<script type="text/javascript">
/* 脚本 */
/* alert("js的弹框000");*/
//js 里函数 就是 java里的方法
function show() {
alert('show方法里的弹框!')
}
</script>
...
<head>
<div onclick="show()">
通过在标签上的 事件动作 on在click点击 的时候 执行 js函数 show()
</div>
外部:
把脚本保存到外部文件中。外部文件通常包含被多个网页使用的代码。外部 JavaScript 文件的文件扩展名是 .js。如需使用外部文件,请在 <script> 标签的 “src” 属性中设置该 .js 文件:
<!DOCTYPE html>
<html>
<body>
<script src="myScript.js"></script>
</body>
</html>
JS输出
JavaScript 可以通过不同的方式来输出数据:
- 使用 window.alert() 弹出警告框。
- 使用 document.write() 方法将内容写到 HTML 文档中。
- 使用 innerHTML 写入到 HTML 元素:如需从 JavaScript 访问某个 HTML 元素,您可以使用 document.getElementById(id) 方法。请使用 “id” 属性来标识 HTML 元素,并 innerHTML 来获取或插入元素内容
- 使用 console.log() 写入到浏览器的控制台。
语法
在编程语言中,一般固定值称为字面量,如 3.14。
3.14 1001 123e5
"John Doe" 'John Doe'
[40, 100, 1, 5, 25, 10]
{firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"}
function myFunction(a, b) { return a * b;}
// 对象寻址方式
var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};
name = person.lastname;
name = person["lastname"];
JavaScript 使用关键字 var 来定义变量, 使用等号来为变量赋值。变量可以通过变量名访问。在指令式语言中,变量通常是可变的。字面量是一个恒定的值。
- js里语句最后的分号可加可不加
- 使用关键字 var let 可以声明变量,const声明常量
- var声明的变量 为 js顶级对象window的属性,为全局变量
- let声明的变量 为 局部变量
**值类型(基本类型)**:字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。
流程控制
let arr = [10, 99, 77, 35, 28, 101];
//遍历
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
console.log('=============');
for (let i of arr) {
console.log(i);
}//iter
console.log('============');
for (let i in arr) {
console.log(arr[i]);
}//forin
console.log('-------------')
//对象
let stu = {
name: 'jacky',
age: 10,
gender: '男',
address: "长大",
study: function () {
alert("学习学习")
}
}
//for-in可以去遍历对象,遍历对象的时候,对象类似一个Map集合 let变量 是 键
for (let stuKey in stu) {
console.log(stu[stuKey]);
}
// 错误处理
try {
console.log(person.name + person.age);//这里有错误
}catch (e) {
console.log(e);
}
Map,Set:ES6新特性 Map,同java里的Map js里只有这两个数组和集合
var map = new Map([["tom",10],["jack",20],["okk",30]])
map.get("tom")
10
map.set("ggz",8)
Map(4) {'tom' => 10, 'jack' => 20, 'okk' => 30, 'ggz' => 8}
idea书写
var map = new Map([["tom",10],["jack",20],["okk",30]])
var age1 = map.get("tom")
console.log(age1);
map.set("qqz",10);
console.log(map);
var set = new Set([1,2,3,3,3,3]); 是一个无序集合
set.add(5); 添加
set.has(3); 是否包含元素
set.delete(1); 删除
set.has(1);
array
let names = ["lucy","jacky","candy","joe","tom"];
function len3(str){
return str.length>=3;
}
console.log(names.every(len3));//对数组的每一个数据 调用 len3
console.log(names.every(name=>name.length>=3));//对数组的每一个数据 调用 判断 长度是否>=3
console.log(names.filter(name=>name.length===3));//过滤 得到 数组
console.log(names.find(name=>name.length==3));//查找 只返回 第一个de 下标
console.log(Array.from(names,name=>name.concat("^_^")));//数组类的工具方法,从某个数组,经过某个计算,得到新数组
console.log(names.join("~"));//使用连接符把数组里的每个数据连接起来返回字符串
console.log(names.map(name=>name.concat("-_-")));//数组里的每个数据 进行映射 映射为新数组
let stack = ["main","show","say","setColor"];
while(stack.length>0){
console.log(stack.pop());//弹栈,从数组末尾删除 并得到数据
}
let stack2 = [];
let i = 1;
while(stack2.length<5){
stack2.push(Math.random()+"="+ i++);//压栈,将数据添加到数组的末尾
}
console.log(stack2);
//total默认是第一个值 name是后面的每一个值,初始化total要放在reduce()中,不能放在log()中
console.log(names.reduce((total,name)=>{return total.concat(name,"=")},"名字大联合:"));
console.log(names.reduce((total,name)=>{return total.concat("=",name)}));
let queue = ["张三","小妹","小梅","黎明"];
console.log("买饭要排队:");
while(queue.length!=0){
console.log(queue.shift());//从数组开头删除 并 返回数据
}
console.log("部分人员名单:"+names.slice(-2));//从倒数第二个开始 直到最后
console.log("部分人员名单:"+names.slice(0,3));//开始的下标 结束的下标(不包括)
console.log(names.some(name=>name.startsWith("j")));//查找有没有一个数组的数据 符合 开头是j
//let names = ["lucy","jacky","candy","joe","tom"];
//splice 先删除 后添加
/*names.splice(1,1,"小李","桃子")
console.log(names);*///在1下标处删除数据,添加 后面的两个数据,此方法会得到 删除的数据
names.splice(1,0,"小小船");//在1小标出删除0个数据,添加后面1个数据
console.log(names);//['lucy', '小小船', 'jacky', 'candy', 'joe', 'tom']
函数
<!-- 函数的定义方式一 -->
function abs(x) {
if (x > 0) {
return x;
} else {
return -x;
//执行到retuen代表函数结束,返回结果,
//如果没有执行return,函数执行完也会返回结果,结果为undefined
}
}
<!-- 函数的定义方式二 -->
//这种形式就是把function (x)当成匿名内部类,但是可以把该类赋值给一个变量,通过变量调用函数
var abs2 = function (x) {
if (x > 0) {
return x;
} else {
return -x;
}
}
<!-- 规避参数不存在和多个参数问题 -->
参数不存在时可设置抛出异常 ,typeof可判断变量类型
var abs3 = function (x) {
if (typeof x !="number"){
throw "Not a Number";
}
if (x > 0) {
return x;
} else {
return -x;
}
}
对于参数过长
// es5所用方法,arguments关键子,代表一个数组,会把所有传进来的参数都放到里面
var abs4 = function (x) {
console.log(x);
for (let i = 0; i<=arguments.length; i++){
console.log(arguments[i]);
}
}
//e6所用方法,rest关键子,剩余的,会把除定义的参数外其他所有传进来的参数都放到里面。...在java代表可变参数
var abs5 = function (x,y,...rest) {
console.log(x);
console.log(y);
console.log(rest);
}
事件
HTML 事件是发生在 HTML 元素上的事情。当在 HTML 页面中使用 JavaScript 时, JavaScript 可以触发这些事件。HTML 元素中可以添加事件属性,使用 JavaScript 代码来添加 HTML 元素。
<button onclick="getElementById('demo').innerHTML=Date()">现在的时间是?</button>
<button onclick="this.innerHTML=Date()">现在的时间是?</button>
事件 | 描述 |
---|---|
onchange | HTML 元素改变 |
onclick | 用户点击 HTML 元素 |
onmouseover | 鼠标指针移动到指定的元素上时发生 |
onmouseout | 用户从一个 HTML 元素上移开鼠标时发生 |
onkeydown | 用户按下键盘按键 |
onload | 浏览器已完成页面的加载 |
更多事件:HTML DOM 事件对象 | 菜鸟教程
事件可以用于处理表单验证,用户输入,用户行为及浏览器动作:
- 页面加载时触发事件
- 页面关闭时触发事件
- 用户点击按钮执行动作
- 验证用户输入内容的合法性……
表单
HTML 表单验证可以通过 JavaScript 来完成。
以下实例代码用于判断表单字段(fname)值是否存在, 如果不存在,就弹出信息,阻止表单提交:
function validateForm() {
var x = document.forms["myForm"]["fname"].value;
if (x == null || x == "") {
alert("需要输入名字。");
return false;
}
}
<form name="myForm" action="demo_form.php" onsubmit="return validateForm()" method="post">
名字: <input type="text" name="fname">
<input type="submit" value="提交">
</form>
数据验证用于确保用户输入的数据是有效的。典型的数据验证有:
- 必需字段是否有输入?
- 用户是否输入了合法的数据?
- 在数字字段是否输入了文本?
大多数情况下,数据验证用于确保用户正确输入数据。数据验证可以使用不同方法来定义,并通过多种方式来调用。
服务端数据验证是在数据提交到服务器上后再验证。客户端数据验证是在数据发送到服务器前,在浏览器上完成验证。
HTML5 新增了 HTML 表单的验证方式:约束验证(constraint validation)。约束验证是表单被提交时浏览器用来实现验证的一种算法。
HTML 约束验证基于:
- HTML 输入属性
- CSS 伪类选择器
- DOM 属性和方法
约束验证 HTML 输入属性
属性 | 描述 |
---|---|
disabled | 规定输入的元素不可用 |
max | 规定输入元素的最大值 |
min | 规定输入元素的最小值 |
pattern | 规定输入元素值的模式 |
required | 规定输入元素字段是必需的 |
type | 规定输入元素的类型 |
约束验证DOM方法:
- checkValidity():如果 input 元素中的数据是合法的返回 true,否则返回 false。
- setCustomValidity():设置 input 元素的 validationMessage 属性,用于自定义错误提示信息的方法。
input 元素的 validity 属性包含一系列关于 validity 数据属性:
属性 | 描述 |
---|---|
customError | 设置为 true, 如果设置了自定义的 validity 信息。 |
patternMismatch | 设置为 true, 如果元素的值不匹配它的模式属性。 |
rangeOverflow | 设置为 true, 如果元素的值大于设置的最大值。 |
rangeUnderflow | 设置为 true, 如果元素的值小于它的最小值。 |
stepMismatch | 设置为 true, 如果元素的值不是按照规定的 step 属性设置。 |
tooLong | 设置为 true, 如果元素的值超过了 maxLength 属性设置的长度。 |
typeMismatch | 设置为 true, 如果元素的值不是预期相匹配的类型。 |
valueMissing | 设置为 true,如果元素 (required 属性) 没有值。 |
valid | 设置为 true,如果元素的值是合法的。 |
例如:如果输入的值大于 100,显示一个信息
<input id="id1" type="number" max="100">
<button onclick="myFunction()">验证</button>
<p id="demo"></p>
<script>function myFunction() {
var txt = "";
if (document.getElementById("id1").validity.rangeOverflow) {
txt = "输入的值太大了";
}
document.getElementById("demo").innerHTML = txt;
}</script>
DOM
文档对象,每个网页都是一个DOM树形结构(HTML 文档中的所有内容都是节点),可以对它进行增删改查操作
增删改查:
//获取各个节点
document.getElementsByTagName('h1');
document.getElementById('p1');
document.getElementsByClassName('p2');
//获取父节点
document.getElementById('f1');
//获取父节点下所有子节点
f1.children
// 删除dom
//删除父节点下的一个子节点,需要先获取父节点,再删除子节点
var son = document.getElementById('p1');
var father = p1.parentElement;
father.removeChild('p1');
// 更新dom
//首先获取到一个节点
document.getElementById('dom');
//操作文本节点,需要全部使用冒号
dom.innerText='123';
//操作html节点
dom.innerHTML='888nbsp;999'
//操作js节点
dom.style.color='red';
dom.style.fontSize='100px';
// 插入dom
var s1 = document.getElementById('s1');
var s2 = document.getElementById('s2');
//append插入一个已存在的节点
s2.appendChild(s1);
//插入一个新的节点
var s5 = document.createElement('p');//新建一个空的p标签,这个标签叫s5,<p>
s5.id = 's5'; //给s5这个标签设置id为s5
s5.innerText = '这是新建的一个p标签'; //给s5设置内容
s2.appendChild(s5);
使用示例:
<script type="text/javascript">
// 1 dom 获取 name属性是hobby 的4个input对象 组合的数组 的长度 把他弹出!
// 2 修改 .hh2 的h2 标题 的 文本内容为 "我的标题2"
// 3 将 #zstd 单元格 所在行 文本居中.
// 4 鼠标悬浮到表格上时 #myjava 被选择!
//文档加载完毕,才去执行,这样就能获得html内容了
window.onload=function () {
alert(document.getElementsByName("hobby").length);
document.getElementById("hh2").innerText = "我的标题2";//这里也可以写innerHTML(标签,文本)
//原生的css里是text-align js里变为驼峰了
document.getElementById("zstd").style.textAlign = "center";
document.getElementsByTagName("table")[0].onmouseover=function () {
document.getElementById("myjava").checked="checked";//true 修改浏览器内存里的对象属性 及时的反应在浏览效果上
//document.getElementById("myjava").setAttribute("checked","checked");//修改源码里的对象的属性
}
}
</script>
// 事件
//move是js里 封装的 事件对象,有很多属性可以调用,有阻止默认行为的方法
function momo(){
//circle跟随鼠标移动而移动!
//鼠标指针的坐标
let x = event.clientX;//event为内置对象
let y = event.clientY;
document.getElementById("circle").style.left = x - 50+"px";
document.getElementById("circle").style.top = y - 50+"px";//?????????????????????????
}
//演示 event对象 的 阻止默认行为的 方法
document.getElementById("a1").onclick = function () {
let b = confirm("确定要打开百度吗?");
if (b===false){
event.preventDefault();
}
}
document.getElementById("province").onchange = function () {
alert("你选择的省份: "+document.getElementById("province").value);
}
document.getElementById("username").onfocus = function () {
document.getElementById("username").style.color = "red";
}
document.getElementById("username").onblur = function () {
document.getElementById("username").style.color = "black";
}
JQuery
<!-- 导入 -->
<script src="../../lib/jquery-3.7.1.js"></script>
<!-- 使用 -->
<!-- 1.先创建一个标签-->
<a href="" id="jquery">点击事件</a>
<script>
<!-- 2.通过jquery进行操作 -->
$('#jquery').click(function (){
//先选择这个id标签,再操作一个事件,这里操作的是点击事件click,事件里面有个函数
alert('hello,jquery');
})
</script>
<ul id="u1">
<li id="u2">ggz</li>
<li class="u3">xmm</li>
<li name="u4">qqz</li>
</ul>
<script>
// jquery获取值和设置值,都要加''
$('#u1 li[id=u2]').text('jjz999');
$('u3').text();
$('#u1 li[name=u4]').html();
// 操作css
$('#u1 li[class=u3]').css({"color":"red"},{"background":"blue"})
$('#u2').css({"fontSize":"50px"})
// 文档的显示与隐藏,先设置display: none;,再对某标签进行隐藏和显示
$('#ul').hide();
$('#ul').show();
</script>
Vue
Vue是一个构建用户界面UI的渐进式javascript框架,渐进式的框架是指可以一步一步的由浅入深的去使用这个框架,该框架可以逐步引入项目。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
Vue2官网(已停止维护):https://v2.cn.vuejs.org/。Vue2教程:介绍 — Vue.js
创建Vue实例
- 准备容器
- 引包(官网) — 开发版本/生产版本
- 创建Vue实例 new Vue()
- 指定配置项,渲染数据
- el:指定挂载点,即Vue所管理的容器
- data:提供数据,使用插值表达式可以渲染出Vue提供的数据
<!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>
<!--
创建Vue实例,初始化渲染
1. 准备容器 (Vue所管理的范围)
2. 引包 (开发版本包 / 生产版本包) 官网
3. 创建实例
4. 添加配置项 => 完成渲染
-->
<!-- 不是Vue管理的范围 -->
<div class="box2">
box2 -- {{ count }}
</div>
<div class="box">
box -- {{ msg }}
</div>
-----------------------------------------------------
<!-- Vue所管理的范围 -->
<div id="app">
<!-- 插值表达式{{data}},渲染data中的数据 -->
<h1>{{ msg }}</h1>
<a href="#">{{ count }}</a>
</div>
<!-- 引入的是开发版本包 - 包含完整的注释和警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script>
// 一旦引入 VueJS核心包,在全局环境,就有了 Vue 构造函数
const app = new Vue({
// 通过 el 配置选择器,指定 Vue 管理的是哪个盒子(这里app对应上面div id=app)
el: '#app',
// 通过 data 提供数据
data: {
msg: 'Hello 传智播客',
count: 666
}
})
</script>
</body>
</html>
响应式特性
Vue 核心特性:响应式:数据变化,视图自动更新,数据驱动视图

指令
概念:指令(Directives)是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。Vue 会根据不同的指令,针对标签实现不同的功能
vue 中的指令按照不同的用途可以分为如下 6 大类:
- 内容渲染指令(v-html、v-text)
- 条件渲染指令(v-show、v-if、v-else、v-else-if)
- 事件绑定指令(v-on)
- 属性绑定指令 (v-bind)
- 双向绑定指令(v-model)
- 列表渲染指令(v-for)
v-text 内容渲染
内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下2 个:
v-text(类似innerText)
- 使用语法:
<p v-text="uname">hello</p>
,意思是将 uame 值渲染到 p 标签中 - 类似 innerText,使用该语法,会覆盖 p 标签原有内容
- 使用语法:
v-html(类似 innerHTML)
- 使用语法:
<p v-html="intro">hello</p>
,意思是将 intro 值渲染到 p 标签中 - 类似 innerHTML,使用该语法,会覆盖 p 标签原有内容
- 类似 innerHTML,使用该语法,能够将HTML标签的样式呈现出来。
- 使用语法:
代码演示:
<div id="app">
<h2>个人信息</h2>
// 既然指令是vue提供的特殊的html属性,所以咱们写的时候就当成属性来用即可
<p v-text="uname">姓名:</p>
<p v-html="intro">简介:</p>
</div>
<script>
const app = new Vue({
el:'#app',
data:{
uname:'张三',
intro:'<h2>这是一个<strong>非常优秀</strong>的boy<h2>'
}
})
</script>
v-if 条件渲染
v-show
原理是切换display:none
控制元素显示隐藏。适合频繁切换显示隐藏的场景(v-show = “表达式” 表达式值为 true 显示, false 隐藏)
v-if
基于条件判断,是否创建 或 移除元素节点。要么显示,要么隐藏,适合不频繁切换的场景
<h3 v-if="age < 18">young</h3>
<h3 v-else-if="age < 40">mid</h3>
<h3 v-else>old</h3>
v-on 事件绑定
- <button v-on:事件名=”内联语句”>按钮
- <button v-on:事件名=”处理函数”>按钮
- <button v-on:事件名=”处理函数(实参)”>按钮
v-on:
简写为 @
双击事件:@dblclick
失去焦点事件:@blur
输入框内容改变、下拉列表改变:@change
<button v-on:click="count++">按钮</button>
<button @click="fn">按钮</button>
<button @click="fn(a,b)">按钮</button>
v-on配置methods函数
<body>
<div id="app">
<button @click="fn">切换显示隐藏</button>
<h1 v-show="isShow">黑马程序员</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app4 = new Vue({
el: '#app',
data: {
isShow: true
},
methods: {
fn () {
// 让提供的所有methods中的函数,this都指向当前实例
// console.log('执行了fn', app.isShow)
// console.log(app3 === this)
this.isShow = !this.isShow
}
}
})
</script>
</body>
参数传递
<body>
<div id="app">
<div class="box">
<h3>小黑自动售货机</h3>
<button @click="buy(5)">可乐5元</button>
<button @click="buy(10)">咖啡10元</button>
<button @click="buy(8)">牛奶8元</button>
</div>
<p>银行卡余额:{{ money }}元</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
money: 100
},
methods: {
buy (price) {
this.money -= price
}
}
})
</script>
</body>
v-bind 属性绑定
**v-bind:**属性名=“表达式”。动态设置html的标签属性 比如:src、url、title
- **v-bind:**可以简写成 => :
比如,有一个图片,它的 src
属性值,是一个图片地址。这个地址在数据 data 中存储。
则可以这样设置属性值:
<img v-bind:src="url" />
<img :src="url" />
(v-bind可以省略)
v-bind增强
为了方便开发者进行样式控制, Vue 扩展了 v-bind 的语法,可以针对 class 类名 和 style 行内样式 进行控制 。
当class动态绑定的是对象时,键就是类名,值就是布尔值,如果值是true,就有这个类,否则没有这个类
<div class="box" :class="{ 类名1: 布尔值, 类名2: 布尔值 }"></div>
适用场景:一个类名,来回切换
当class动态绑定的是数组时 → 数组中所有的类,都会添加到盒子上,本质就是一个 class 列表
<div class="box" :class="[ 类名1, 类名2, 类名3 ]"></div>
使用场景:批量添加或删除类
操作style
<div class="box" :style="{ CSS属性名1: CSS属性值, CSS属性名2: CSS属性值 }"></div>
v-for 列表渲染
v-for 基于数据循环,多次渲染整个元素
v-for 指令需要使用 (item, index) in arr
形式的特殊语法,其中:
- item 是数组中的每一项
- index 是每一项的索引,不需要可以省略
- arr 是被遍历的数组
此语法也可以遍历对象和数字
<ul>
// key作用:给元素添加的唯一标识,便于Vue进行列表项的正确排序复用
<li v-for="(item,index) in booksList" :key="item.id">
<span>{{ item.name }}</span>
<span>{{ item.author }}</span>
</li>
</ul>
v-model 双向绑定
v-model 用于表单元素。所谓双向绑定就是:
- 数据改变后,呈现的页面结果会更新
- 页面结果更新后,数据也会随之而变
作用: 给表单元素(input、radio、select)使用,双向绑定数据,可以快速 获取 或 设置 表单元素内容
<body>
<div id="app">
账户:<input type="text" v-model="username"> <br><br>
密码:<input type="password" v-model="password"> <br><br>
<button @click="login">登录</button>
<button @click="reset">重置</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
username: '',
password: ''
},
methods: {
login () {
console.log(this.username, this.password)
},
reset () {
this.username = ''
this.password = ''
}
}
})
</script>
</body>
v-model增强
常见的表单元素都可以用 V-model
绑定关联 → 快速 获取 或 设置 表单元素的值
会根据控件类型自动选取正确的方法来更新元素
<input type="checkbox" v-model="isSingle">
<input v-model="gender" type="radio" name="gender" value="1">男
<input v-model="gender" type="radio" name="gender" value="2">女
<select v-model="cityId">
<option value="101">北京</option>
<option value="102">上海</option>
</select>
const app = new Vue({
el: '#app',
data: {
isSingle: false,
gender: "1",
cityId: '101',
}
})
指令修饰符
所谓指令修饰符就是通过“.”指明一些指令后缀 不同的后缀封装了不同的处理操作 —> 简化代码
@keyup.enter
键盘回车enter键监听
v-model.trim
去除首尾空格
v-model.number
转数字
@click.stop
阻止冒泡
computed计算属性
基于现有的数据,计算出来的新属性。 依赖的数据变化,自动重新计算。
- 声明在 computed 配置项中,一个计算属性对应一个函数
- 使用起来和普通属性一样使用
computed: {
计算属性名(){
基于现有数据,编写求值逻辑
return 结果
}
}
<body>
<div id="app">
<h3>小黑的礼物清单</h3>
<table>
<tr>
<th>名字</th>
<th>数量</th>
</tr>
<tr v-for="(item, index) in list" :key="item.id">
<td>{{ item.name }}</td>
<td>{{ item.num }}个</td>
</tr>
</table>
<!-- 目标:统计求和,求得礼物总数 -->
<p>礼物总数:{{ totalCount }} 个</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
// 现有的数据
list: [
{ id: 1, name: '篮球', num: 1 },
{ id: 2, name: '玩具', num: 2 },
{ id: 3, name: '铅笔', num: 5 },
]
},
computed:{
//注意是属性不是函数
totalCount(){
//0表示求和起始值,reduce遍历list,将每个item的值加上后返回给sum
let total= this.list.reduce((sum, item) => sum + item.num, 0)
return total
}
}
})
</script>
</body>
- computed计算属性
作用:封装了一段对于数据的处理,求得一个结果
缓存特性:计算属性会对计算出来的结果缓存,再次使用直接读取缓存,依赖项变化了,会自动重新计算 -> 并再次缓存 - methods方法:
作用:给实例提供一个方法,调用以处理业务逻辑
watch侦听器(监视器)
监视数据变化,执行一些业务逻辑或异步操作
data: {
words: '苹果',
obj: {
words: '苹果'
}
},
watch: {
// 该方法会在数据变化时,触发执行
数据属性名 (newValue, oldValue) {
一些业务逻辑 或 异步操作。
},
'对象.属性名' (newValue, oldValue) {
一些业务逻辑 或 异步操作。
}
}
示例:
<body>
<div id="app">
<!-- 条件选择框 -->
<div class="query">
<span>翻译成的语言:</span>
<select>
<option value="italy">意大利</option>
<option value="english">英语</option>
<option value="german">德语</option>
</select>
</div>
<!-- 翻译框 -->
<div class="box">
<div class="input-wrap">
<textarea v-model="obj.words"></textarea>
<span><i>⌨️</i>文档翻译</span>
</div>
<div class="output-wrap">
<div class="transbox">{{ result }}</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 接口地址:https://applet-base-api-t.itheima.net/api/translate
// 请求方式:get
// 请求参数:
// (1)words:需要被翻译的文本(必传)
// (2)lang: 需要被翻译成的语言(可选)默认值-意大利
// -----------------------------------------------
const app = new Vue({
el: '#app',
data: {
// words: ''
obj: {
words: ''
},
result:'',//翻译结果
timer: null
},
// 具体讲解:(1) watch语法 (2) 具体业务实现
watch: {
// 该方法会在数据变化时调用执行
// newValue新值, oldValue老值(一般不用)
// words (newValue) {
// console.log('变化了', newValue)
// }
'obj.words' (newValue) {
//console.log('变化了', newValue)
//防抖:延迟执行 -> 干啥事先等一等,延迟一会,一段时间内没有再次触发,才执行
clearTimeout(this.timer)
this.timer = setTimeout(async () => {
//这里是ajax的内容
const res = await axios({
url: 'https://applet-base-api-t.itheima.net/api/translate',
params:{
words:newValue
}
})
this.result = res.data.data
console.log(res.data.data)
}, 300)
}
}
})
</script>
</body>
完整写法
添加额外配置项
(1)deep:true 对复杂类型深度监视
(2)immediate:true 初始化立刻执行一次handler方法
// 具体讲解:(1) watch语法 (2) 具体业务实现
watch: {
obj: {
deep: true, //深度监视
immediate: true, //立刻执行,一进入页面handler立刻执行
handler( newValue ){
// 防抖:延迟执行 -> 干啥事先等一等,延迟一会,一段时间内没有再次触发,才执行
clearTimeout(this.timer)
this.timer = setTimeout(async () => {
//这里是ajax的内容
const res = await axios({
url: 'https://applet-base-api-t.itheima.net/api/translate',
params:newValue
})
this.result = res.data.data
console.log(res.data.data)
}, 300)
}
}
Vue生命周期
- 创建阶段:创建响应式数据 发送初始化渲染请求
- 挂载阶段:渲染模版 操作dom
- 更新阶段:修改数据、更新视图
- 销毁阶段:销毁实例

Vue生命周期过程中,会自动运行一些函数(created&mounted),被称为生命周期钩子,让开发者可以在特定阶段运行自己的代码

工程化开发
vue开发的两种方式:
- 核心包传统开发模式:基于html / css / js 文件,直接引入核心包,开发 Vue。
- 工程化开发模式:基于构建工具(例如:webpack)的环境中开发Vue。
Vue CLI 是 Vue 官方提供的一个全局命令工具 安装:npm i @vue/cli -g
可以帮助我们快速创建一个开发Vue项目的标准化基础架子【集成 webpack 配置】

- 组件化:一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为
好处:便于维护,利于复用,有利于提升开发效率
组件分类:普通组件、根组件 - 根组件:整个应用最上层的组件,包括所有普通小组件
App.vue文件
- template:结构(Vue2中有且只能一个元素)
- script:js逻辑
- style:样式(可支持less,需要装包)
<template>
<!-- Vue2中只能有一个根元素 -->
<div class="app" @click="fn()">
我是结构
</div>
</template>
<script>
export default{
methods:{
fn(){
alert("hello")
}
}
}
</script>
<style lang="less">
.app {
width: 400px;
height: 400px;
background-color: pink;
}
</style>
组件注册
局部注册
- 创建.vue文件(三个组成部分:Header,Main,Footer)
- 在使用的组件内(例如app.vue根组件)导入并注册
<!-- App.vue文件 -->
<script>
import HmHeader from './components/HmHeader.vue'
import HmMain from './components/HmMain.vue'
import HmFooter from './components/HmFooter.vue'
export default {
components:{
HmHeader:HmHeader,
HmMain,
HmFooter
}
}
</script>
全局注册
- 创建.vue文件(三个组成部分)
- main.js中进行全局注册
//导入需要全局注册的组件
import HmButton from './components/HmButton'
//调用Vue.component进行全局注册
//Vue.component('组件名',组件对象)
Vue.component('HmButton', HmButton)
组件组成与通信
写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。
全局样式: 默认组件中的样式会作用到全局,任何一个组件中都会受到此样式的影响
局部样式: 可以给组件加上scoped 属性,可以让样式只作用于当前组件
<style lang="less" scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 200px;
min-height: 400px;
}
.el-menu {
height: 100%;
border: none;
h4 {
color: #fff;
text-align: center;
line-height: 10px;
}
}
.router-link-active {
text-decoration: none;
color: #fff;
font-style: normal;
}
i {
text-decoration: none;
color: white;
font-style: normal;
}
</style>
一个组件的 data 选项必须是一个函数。目的是为了:保证每个组件实例,维护独立的一份数据对象。
每次创建新的组件实例,都会新执行一次data 函数,得到一个新对象。
组件通信
组件通信,就是指组件与组件之间的数据传递
- 组件的数据是独立的,无法直接访问其他组件的数据。
- 想使用其他组件的数据,就需要组件通信
两种组件关系分类 和 对应的组件通信方案
- 父子关系 → props & $emit
- props:组件上 注册的一些 自定义属性,用于父组件向子组件传递数据
- 可以 传递 任意数量/任意类型 的prop
- 非父子关系 → provide & inject 或 eventbys
- 通用方案 → vuex
父子通信
父->子

子->父

props校验
为prop指定验证要求,不符合要求,控制台就会有错误提示→帮助开发者,快速发现错误
props: {
校验的属性名: {
type: 类型, // Number String Boolean ...
required: true, // 是否必填
default: 默认值, // 默认值
validator (value) {
// 自定义校验逻辑
return 是否通过校验
}
}
},
export default {
// 完整写法(类型、默认值、非空、自定义校验)
props: {
w: {
type: Number,
//required: true,
default: 0,
validator(val) {
// console.log(val)
if (val >= 100 || val <= 0) {
console.error('传入的范围必须是0-100之间')
return false
} else {
return true
}
},
},
},
}
props&data
共同点:都可以给组件提供数据
区别:
- data的数据是自己的 → 随便改
- props的数据是外部的 → 不能直接改,要遵循单向数据流
单向数据流:父级prop的数据更新,会向下流动,影响子组件。这个数据流动是单向的。
非父子通信
event bus 事件总线
创建一个都能访问的事件总线 (空Vue实例)
import Vue from 'vue' const Bus = new Vue() export default Bus
A组件(接受方),监听Bus的 $on事件
created () { Bus.$on('sendMsg', (msg) => { this.msg = msg }) }
B组件(发送方),触发Bus的$emit事件
Bus.$emit('sendMsg', '这是一个消息')
provide&inject
跨层级数据共享
- 父组件 provide提供数据
export default {
provide () {
return {
// 普通类型【非响应式】
color: this.color,
// 复杂类型【响应式】
userInfo: this.userInfo,
}
}
}
2.子/孙组件 inject获取数据
export default {
inject: ['color','userInfo'],
created () {
console.log(this.color, this.userInfo)
}
}
- provide提供的简单类型的数据不是响应式的,复杂类型数据是响应式。(推荐提供复杂类型数据)
- 子/孙组件通过inject获取的数据,不能在自身组件内修改
组件双向绑定
表单类组件封装 → 实现子组件和父组件数据的双向绑定
①父传子:数据应该是父组件props传递过来的,v-model拆解绑定数据
②子传父:监听输入,子传父传值给父组件修改
本质:实现了子组件和父组件数据的双向绑定
<!--1.父组件给子组件传递属性cityId 4.父组件监听到'事件名',更新selectID-->
<BaseSelect :cityId="selectId" @事件名="selectId = $event"></BaseSelect>
<!--3.子组件BaseSelect.vue触发事件handlechange-->
<select :value="cityId" @change="handleChange">...</select>
<script>
// 2.子组件props接收父组件传值
props: {
cityId:String
},
methods: {
// 对应3.触发事件handlechange,给父组件发送消息通知
handleChange (e) {
this.$emit('事件名', e.target.value)
}
}
</script>
v-model简化双向绑定
父组件v-model简化代码,实现子组件和父组件数据双向绑定
①子组件中:props通过value接受,事件触发input
②父组件中:v-model给组件直接绑数据
<!--父组件-->
<BaseSelect v-model="selectId"></BaseSelect>
<!--子组件-->
<select :value="value" @change="handleChange">...</select>
<script>
//子组件
props: {
value:String
},
methods: {
handleChange (e) {
this.$emit('input', e.target.value)
}
}
</script>
.sync修饰符
作用:可以实现子组件和父组件数据的双向绑定,简化代码
特点:prop属性名,可以自定义,非固定为value
场景:封装弹框类的基础组件,visible属性 true显示 false隐藏
本质:就是 :属性名 和 @update:属性名 合写
<!--父组件-->
<BaseDialog :visible.sync="isShow"></BaseDialog>
<script>
//子组件
props:{
visible:Boolean
},
methods:{
// 关闭弹窗,触发父组件属性隐藏
close () {
this.$emit('update:visible', false)
}
}
</script>
ref 和 $refs
作用:利用 ref 和 $refs 可以用于 获取 dom 元素,或 组件实例
特点:查找范围 → 当前组件内(更精确稳定)
① 获取dom:
目标标签 - 添加 ref 属性
<div ref="chartRef">我是渲染图标的容器</div>
获取时,通过 this.$refs.xxx,获取目标标签
<script>
mounted() {
console.log(this.$refs.chartRef)
},
</script>
注意:之前只用document.querySelect(‘.box’) 获取的是整个页面中的盒子
异步更新
- Vue是异步更新DOM的
- 想要在DOM更新完成之后做某件事,可以使用$nextTick
语法: this.$nextTick(函数体)
this.$nextTick(() => {
this.$refs.inp.focus()
})
注意:$nextTick 内的函数体 一定是箭头函数,这样才能让函数内部的this指向Vue实例
单页应用
单页应用程序:SPA【Single Page Application】是指所有的功能都在一个html页面上实现
单页应用网站: 网易云音乐 https://music.163.com/
多页应用网站:京东 https://jd.com/

单页应用类网站:系统类网站 / 内部网站 / 文档类网站 / 移动端站点
多页应用类网站:公司官网 / 电商类网站
路由
单页面应用程序,之所以开发效率高,性能好,用户体验好
最大的原因就是:页面按需更新。比如当点击【发现音乐】和【关注】时,只是更新下面部分内容,对于头部是不更新的

Vue中的路由:路径和组件的映射关系
下载 VueRouter 模块到当前工程,版本3.6.5
yarn add vue-router@3.6.5
main.js中引入VueRouter
import VueRouter from 'vue-router'
安装注册
Vue.use(VueRouter)
创建路由对象
const router = new VueRouter({ routes:[...] })
注入,将路由对象注入到new Vue实例中,建立关联
new Vue({ render: h => h(App), router:router }).$mount('#app')
当我们配置完以上5步之后 就可以看到浏览器地址栏中的路由 变成了 /#/的形式。表示项目的路由已经被Vue-Router管理了

配置导航,配置路由出口(路径匹配的组件显示的位置)
App.vue
<div class="footer_wrap">
<a href="#/find">发现音乐</a>
<a href="#/my">我的音乐</a>
<a href="#/friend">朋友</a>
</div>
<div class="top">
<router-view></router-view>
</div>
前端框架
经典(以此为准):PanJiaChen/vue-element-admin: 🎉 A magical vue admin https://panjiachen.github.io/vue-element-admin
启动解析
1.main.js入口
示例结构:
import Vue from 'vue'; // 引入 Vue
import App from './App'; // 引入根组件
import router from './router'; // 引入路由(如果有)
Vue.config.productionTip = false; // 禁用生产模式下的提示
new Vue({
el: '#app', // 将 Vue 实例挂载到 id 为 'app' 的 DOM 元素上
render: h => h(App), // 渲染根组件 App
router, // 路由配置(如果有)
})
2.App.vue
在 Vue 项目中,App.vue
是根组件。它通过 <router-view />
渲染页面内容。
Vue Router 是 Vue 官方的客户端路由解决方案。
客户端路由的作用是在单页应用 (SPA) 中将浏览器的 URL 和用户看到的内容绑定起来。当用户在应用中浏览不同页面时,URL 会随之更新,但页面不需要从服务器重新加载。
Vue Router 基于 Vue 的组件系统构建,你可以通过配置路由来告诉 Vue Router 为每个 URL 路径显示哪些组件。
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
3.router
Vue Router 管理应用中的路由和页面导航。路由配置文件router/index.js
示例:
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/views/Home.vue';
import About from '@/views/About.vue';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
});
实际页面内容的渲染
- 加载根组件(
App.vue
):- 当 Vue 应用启动时,
App.vue
会被加载并渲染,其中包含了<router-view />
。
- 当 Vue 应用启动时,
- 匹配路由:
- 根据 URL 路径,Vue Router 会匹配到相应的路由。
- 比如,当用户访问
http://localhost:8080/
时,Vue Router 会匹配到/
路径,并加载Home.vue
组件。
- 渲染对应的组件:
- Vue Router 会将匹配到的组件(例如
Home.vue
或About.vue
)插入到App.vue
中的<router-view />
部分。 - 最终,用户在页面上看到的就是
Home.vue
或About.vue
组件的内容。
- Vue Router 会将匹配到的组件(例如
布局
Layout
页面整体布局是一个产品最外层的框架结构,往往会包含导航、侧边栏、面包屑以及内容等。
vue-router 路由嵌套:Vue Router 的路由嵌套机制允许在一个路由组件中嵌套显示另一个路由组件。通常在布局(如 Layout
)中,使用嵌套路由来组织子页面或功能模块。这种嵌套机制通过 <router-view />
占位符来渲染子路由组件。
一般情况下,你增加或者修改页面只会影响 app-main
这个主体区域。其它配置在 layout
中的内容如:侧边栏或者导航栏都是不会随着你主体页面变化而变化的。
/foo /bar
+------------------+ +-----------------+
| layout | | layout |
| +--------------+ | | +-------------+ |
| | foo.vue | | +------------> | | bar.vue | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
当然你也可以一个项目里面使用多个不同的 layout
,只要在你想作用的路由父级上引用它就可以了。
父路由和子路由:
- 父路由:是定义在路由配置中,包含子路由的路由。通常,父路由配置会有一个
<router-view />
占位符,用于渲染子路由。 - 子路由:是嵌套在父路由下的路由,子路由通过
children
属性来定义。
路由渲染顺序:
当用户访问某个路径时,Vue Router 会根据路径匹配到父路由,再匹配到子路由。
父路由组件渲染时,会渲染一个
<router-view />
作为占位符,子路由组件会被插入到这个占位符中。
1. 路由配置 (router/index.js
)
javascript复制代码import Vue from 'vue';
import Router from 'vue-router';
import Layout from '@/layouts/Layout'; // 引入 Layout 布局组件
import Dashboard from '@/views/dashboard/index'; // 引入 Dashboard 子页面
import Profile from '@/views/profile/index'; // 引入 Profile 子页面
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
component: Layout, // 父路由使用 Layout 布局组件
redirect: '/dashboard', // 默认重定向到 /dashboard
children: [
{
path: 'dashboard', // 子路由的路径为 'dashboard'
component: Dashboard, // 子路由渲染 Dashboard 组件
name: 'Dashboard', // 子路由的名称
meta: { title: 'Dashboard', icon: 'dashboard' }
},
{
path: 'profile', // 另一个子路由的路径为 'profile'
component: Profile, // 子路由渲染 Profile 组件
name: 'Profile',
meta: { title: 'Profile', icon: 'user' }
}
]
}
]
});
2. 父路由布局组件 (Layout.vue
)
vue复制代码<template>
<div class="layout">
<!-- 侧边栏组件 -->
<Sidebar />
<!-- 主体内容区域 -->
<div class="main-content">
<!-- 导航栏组件 -->
<Navbar />
<!-- 子路由渲染区 -->
<router-view /> <!-- 这个 <router-view /> 会渲染子路由组件 (如 Dashboard 或 Profile) -->
</div>
</div>
</template>
<script>
import Sidebar from '@/components/Sidebar';
import Navbar from '@/components/Navbar';
export default {
name: 'Layout',
components: {
Sidebar,
Navbar
}
}
</script>
3. 子路由组件 (Dashboard.vue
和 Profile.vue
)
Dashboard.vue
vue复制代码<template>
<div class="dashboard">
<h1>Dashboard</h1>
<p>欢迎来到 Dashboard 页面</p>
</div>
</template>
<script>
export default {
name: 'Dashboard'
}
</script>
Profile.vue
vue复制代码<template>
<div class="profile">
<h1>Profile</h1>
<p>这是用户的个人资料页面</p>
</div>
</template>
<script>
export default {
name: 'Profile'
}
</script>
实际layout代码
@/layout layout下index.vue
<template>
<div :class="classObj" class="app-wrapper">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<sidebar class="sidebar-container" />
<div :class="{hasTagsView:needTagsView}" class="main-container">
<div :class="{'fixed-header':fixedHeader}">
<navbar />
<tags-view v-if="needTagsView" />
</div>
<!-- 子组件app-main里面定义了子路由router-view -- 子路由渲染区 -->
<app-main />
<right-panel v-if="showSettings">
<settings />
</right-panel>
</div>
</div>
</template>
<script>
import RightPanel from '@/components/RightPanel'
import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
import ResizeMixin from './mixin/ResizeHandler'
import { mapState } from 'vuex'
export default {
name: 'Layout',
// 引入并注册子组件,作为layout的一部分进行渲染
components: {
AppMain,
Navbar,
RightPanel,
Settings,
Sidebar,
TagsView
},
// 使用的 mixins,提供了组件间复用的功能
mixins: [ResizeMixin],
// 计算属性
computed: {
// 使用 mapState 辅助函数映射 Vuex store 中的状态到当前组件的计算属性
...mapState({
// 获取 Vuex store 中的 sidebar 状态,表示侧边栏的开关
sidebar: state => state.app.sidebar,
device: state => state.app.device,
showSettings: state => state.settings.showSettings,
needTagsView: state => state.settings.tagsView,
fixedHeader: state => state.settings.fixedHeader
}),
// 计算类名对象,返回一个动态的 class 对象
classObj() {
return {
// 根据 sidebar 的状态动态切换类名
hideSidebar: !this.sidebar.opened, // 侧边栏关闭时,应用 'hideSidebar' 类
openSidebar: this.sidebar.opened, // 侧边栏打开时,应用 'openSidebar' 类
withoutAnimation: this.sidebar.withoutAnimation, // 判断是否禁用动画
mobile: this.device === 'mobile'
}
}
},
methods: {
// 处理点击外部区域的事件,用来关闭侧边栏
handleClickOutside() {
// 使用 Vuex 的 action 来关闭侧边栏
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
}
}
}
</script>
**
<router-view />
**:Layout
组件本身并不直接渲染内容,而是作为页面的框架,提供固定的布局部分(如侧边栏、导航栏等)。它通过<router-view />
来渲染子路由的内容。此处没有直接放置<router-view />
,而是放置了AppMain
组件,AppMain
组件会在其中继续嵌套一个<router-view />
,从而实现多层嵌套。AppMain
组件:Layout
渲染了AppMain
组件,AppMain
内部还通过<router-view />
渲染子路由内容(例如Dashboard
或Profile
)。
app-main
<template>
<!-- 主内容区域 -->
<section class="app-main">
<!-- 过渡动画:fade-transform -->
<transition name="fade-transform" mode="out-in">
<!-- keep-alive 用于缓存视图,以避免重新加载组件 -->
<keep-alive :include="cachedViews">
<!-- 渲染路由的子组件,key 用于控制视图的缓存和刷新 -->
<router-view :key="key" />
</keep-alive>
</transition>
</section>
</template>
<script>
export default {
name: 'AppMain',
computed: {
// 计算属性:获取要缓存的视图列表
cachedViews() {
// 从 Vuex 存储中获取缓存视图的列表
return this.$store.state.tagsView.cachedViews
},
// 计算属性:返回当前路由的路径
key() {
// 使用当前路由的路径作为唯一的 key 来控制视图缓存和刷新
return this.$route.path
}
}
}
</script>
transition
:使用 Vue 的过渡系统,为路由切换添加过渡动画。<keep-alive>
标签:Vue 的内置组件,用于缓存页面组件,以避免频繁的销毁和重新创建。:include="cachedViews"
:指定要缓存的组件列表。cachedViews
是一个计算属性,从 Vuex 获取已缓存的视图。- 这样配置后,只有在
cachedViews
中列出的视图才会被缓存,从而提升性能,避免频繁地销毁和创建页面组件。
key
计算属性:返回当前路由的路径。- 这个
key
属性用于在每次路由切换时更新<router-view>
,确保组件在路由变化时重新渲染。 - 通过使用路由的
path
作为key
,可以让 Vue 在切换路由时正确地处理组件的缓存与更新。
- 这个
Vuex store
Vuex store 是 Vue.js 官方提供的一个状态管理库,用于管理应用中的共享状态。在 Vue.js 中,状态通常指的是数据(如用户信息、产品列表、界面设置等),而这些状态需要在应用的多个组件之间共享和管理。Vuex 通过集中式的存储和管理这些状态,使得不同组件之间的数据流变得更加清晰和可维护。
Vuex store 中的状态是响应式的,任何使用到这些状态的组件都会在状态变化时自动更新。
Vuex store 基于以下几个核心概念:
- State(状态):用于存储应用的共享数据,Vuex 中的状态就类似于一个全局的数据源。
- Getters(获取器):类似于计算属性(computed),用于从 Vuex store 中派生出数据。Getters 用来获取或过滤状态中的数据。
- Mutations(突变):用来同步修改 Vuex store 中的状态。所有对状态的改变必须通过 mutation 来进行。
- Actions(动作):用于处理异步操作和业务逻辑,它们会提交 mutations 来改变状态。
- Modules(模块):Vuex 支持将 store 分割成多个模块,每个模块拥有自己的 state、mutations、actions 和 getters,以便组织大型应用的状态。
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
// 安装 Vuex 插件
Vue.use(Vuex);
const store = new Vuex.Store({
// 状态 (store 中的数据)
state: {
counter: 0,
user: null,
},
// 获取器 (计算属性,派生数据)
getters: {
counterDouble: (state) => state.counter * 2,
userName: (state) => state.user ? state.user.name : 'Guest',
},
// 突变 (同步修改状态)
mutations: {
increment(state) {
state.counter++;
},
setUser(state, user) {
state.user = user;
},
},
// 动作 (可以进行异步操作)
actions: {
fetchUser({ commit }) {
// 模拟异步获取用户数据
setTimeout(() => {
const user = { name: 'John Doe', age: 30 };
commit('setUser', user); // 提交 mutation
}, 1000);
},
},
// 模块 (支持模块化管理状态)
modules: {
// 可以定义多个子模块来管理不同的 state
},
});
export default store;
配置store:
import Vue from 'vue';
import App from './App.vue';
import store from './store'; // 引入 Vuex store
new Vue({
render: (h) => h(App),
store, // 将 Vuex store 注入到 Vue 实例
}).$mount('#app');
参考
w3school:HTML 教程
前端三件套简要笔记_后端转前端 html js css怎么学习-CSDN博客
黑马Vue2+Vue3笔记_vue学习笔记黑马-CSDN博客
VUE学习笔记(黑马2023版 第四天)_vue 黑马2023版 源码-CSDN博客
PanJiaChen/vue-element-admin: 🎉 A magical vue admin https://panjiachen.github.io/vue-element-admin