前言
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它的设计目标是通过采用易于上手的结构和强大的功能,使前端开发变得更加简便和高效。以下是 Vue.js 的一些关键特性和优点:
核心特性
-
声明式渲染
- Vue.js 使用声明式语法来描述用户界面,数据和视图是双向绑定的。当数据变化时,视图会自动更新。
-
组件系统
- Vue.js 提供了一个灵活的组件系统,允许开发者将 UI 分解成可复用的组件,每个组件都有自己的逻辑和样式。
-
单文件组件 (SFC)
- Vue.js 允许开发者将 HTML、CSS 和 JavaScript 放在同一个
.vue
文件中,这样可以更容易地管理组件。
- Vue.js 允许开发者将 HTML、CSS 和 JavaScript 放在同一个
-
虚拟 DOM
- Vue.js 使用虚拟 DOM 来优化更新过程,通过最小化实际 DOM 操作来提高性能。
-
反应式数据绑定
- Vue.js 提供了响应式的数据绑定系统,使得数据与 DOM 之间的同步变得简单和高效。
-
指令
- Vue.js 提供了一组内置指令(如
v-bind
、v-model
和v-for
),帮助开发者轻松地操作 DOM。
- Vue.js 提供了一组内置指令(如
优点
-
易于上手
- Vue.js 的学习曲线较低,适合新手入门,并且文档详细、社区活跃。
-
灵活性
- Vue.js 可以与现有项目集成,也可以用于构建复杂的单页面应用(SPA)。
-
性能高效
- 得益于虚拟 DOM 和响应式系统,Vue.js 在处理大量数据更新时表现出色。
-
生态系统
- Vue.js 拥有丰富的生态系统,包括 Vue Router、Vuex、Vue CLI 等工具和库,支持开发者在不同场景下使用。
-
强大的社区支持
- Vue.js 有一个全球活跃的社区,提供了大量的插件、教程和支持资源。
知识点
1. 通过 v-if v-else 选择渲染数据,没有渲染的则销毁数据
2. v- for 遍历渲染数据
3. v-bind 绑定 class 实现条件渲染
4. @click 绑定点击事件
5. @click.prevent 阻止跳转
6. filter() 方法删除数组中的元素
7. v-model 绑定元素实时获取数据
8. v-model.trim 删除字符串的头尾空白符实现过滤
9. v-model.number 转换类型为数字
10. unshift() 方法向数组的开头添加一个或更多元素
11. 限制添加数据的规则
12. 插值语法更新数据
13. 计算属性统计数据
14. .toFixed(2) 保留两位小数
项目效果
初始状态
删除数据
添加数据
源代码
.score-case {
width: 1000px;
margin: 50px auto;
display: flex;
}
.score-case .table {
flex: 4;
}
.score-case .table table {
width: 100%;
border-spacing: 0;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
}
.score-case .table table th {
background: #f5f5f5;
}
.score-case .table table tr:hover td {
background: #f5f5f5;
}
.score-case .table table td,
.score-case .table table th {
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
text-align: center;
padding: 10px;
}
.score-case .table table td.red,
.score-case .table table th.red {
color: red;
}
.score-case .table .none {
height: 100px;
line-height: 100px;
color: #999;
}
.score-case .form {
flex: 1;
padding: 20px;
}
.score-case .form .form-item {
display: flex;
margin-bottom: 20px;
align-items: center;
}
.score-case .form .form-item .label {
width: 60px;
text-align: right;
font-size: 14px;
}
.score-case .form .form-item .input {
flex: 1;
}
.score-case .form .form-item input,
.score-case .form .form-item select {
appearance: none;
outline: none;
border: 1px solid #ccc;
width: 200px;
height: 40px;
box-sizing: border-box;
padding: 10px;
color: #666;
}
.score-case .form .form-item input::placeholder {
color: #666;
}
.score-case .form .form-item .cancel,
.score-case .form .form-item .submit {
appearance: none;
outline: none;
border: 1px solid #ccc;
border-radius: 4px;
padding: 4px 10px;
margin-right: 10px;
font-size: 12px;
background: #ccc;
}
.score-case .form .form-item .submit {
border-color: #069;
background: #069;
color: #fff;
}
<!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" />
<link rel="stylesheet" href="./static/styles/index.css" />
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="app" class="score-case">
<div class="table">
<table>
<thead>
<tr>
<th>编号</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<!-- 1 -->
<!-- 这里有两个 tbody,只能保留一个 -->
<!-- 通过 v-if v-else 如果有成绩则渲染,没有则显示无数据 -->
<!-- 如果使用 v-show 则在页面中 tbody 节点还是存在只是不展示,而 v-if v-else 则直接销毁 -->
<tbody v-if="list.length > 0">
<!-- v-for 遍历渲染数据 -->
<tr v-for="(item, index) in list" :key="item">
<td>{{ index + 1 }}</td>
<td>{{ item.subject }}</td>
<!-- 需求:不及格加红 -->
<!-- v-bind 绑定 class -->
<td :class="{ red: item.score < 60 }">{{ item.score }}</td>
<!-- @click 绑定点击事件 -->
<!-- .prevent 阻止跳转 -->
<td><a @click.prevent="del(item.id)" href="#">删除</a></td>
</tr>
</tbody>
<tbody v-else>
<tr>
<td colspan="5">
<span class="none">暂无数据</span>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5">
<span>总分:{{ totalScore }}</span>
<span style="margin-left: 50px">平均分:{{ averageScore }}</span>
</td>
</tr>
</tfoot>
</table>
</div>
<div class="form">
<div class="form-item">
<div class="label">科目:</div>
<div class="input">
<!-- v-model 绑定元素实时获取数据 -->
<!-- .trim 删除字符串的头尾空白符实现过滤 -->
<input v-model.trim="subject" type="text" placeholder="请输入科目"/>
</div>
</div>
<div class="form-item">
<div class="label">分数:</div>
<div class="input">
<!-- .number 转为数字 -->
<input v-model.number="score" type="text" placeholder="请输入分数"/>
</div>
</div>
<div class="form-item">
<div class="label"></div>
<div class="input">
<button @click="add()" class="submit">添加</button>
</div>
</div>
</div>
</div>
<script src="../vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
list: [
{ id: 1, subject: '语文', score: 20 },
{ id: 7, subject: '数学', score: 99 },
{ id: 12, subject: '英语', score: 70 },
],
subject: '',
score: ''
},
// computed 是一个对象,其中的每个属性都是一个计算属性
computed: {
totalScore () {
// reduce 方法接收两个参数:一个回调函数和一个初始值。
// 回调函数接收两个参数:sum(累加器)和 item(当前项)。
// 回调函数的返回值将作为下一次调用的 sum 参数。
// 初始值是 0,表示累加开始时的值。
return this.list.reduce((sum, item) => sum + item.score, 0)
},
averageScore () {
// 除数不能为 0
if (this.list.length !== 0) {
// toFixed(2) 结果保留两位小数
return this.totalScore / this.list.length.toFixed(2)
}
return 0
}
},
methods: {
del (id) {
// filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
// 这是一个箭头函数,它接收数组中的每个元素作为参数(在这里是 item)。
// item.id !== id:这是一个比较操作,检查 item 的 id 属性是否不等于传递给 filter 方法的 id 参数。如果不等于,返回 true;如果等于,返回 false
this.list = this.list.filter(item => item.id !== id)
},
add () {
// 当用户输入为空时,不让添加
if (this.subject | this.score === '') {
alert('输入不可为空')
return
}
if (typeof this.score !== 'number') {
alert('成绩请输入数字')
return
}
// unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度
this.list.unshift({
// id 不用管,因为上面写好了,添加就是 1
id: Date(),
subject: this.subject,
score: this.score
})
// 输入完后清空输入框的内容
this.subject = '',
this.score = ''
}
},
})
</script>
</body>
</html>