Vue 是一款用于 构建用户界面 的 渐进式 的 JavaScript 框架
官方网站:https://cn.vuejs.org
- 构建用户界面: 基于数据就能渲染出用户看到的界面
- 渐进式: 循序渐进. 不需要把所有的组件、语法全部学习完毕才可以使用 Vue. 可以需要什么用什么.
- 框架: 是一套完整的项目解决方案,用于快速构建项目.
VUE 只需要具备基础的 HTML 和 JavaScript 知识即可快速上手!
总的来说, VUE 主要的工作是通过调用预定义的 JS 组件, 快速将数据渲染到页面上.
并且确保当数据变化时, 网页能够自动更新.
入门案例
1). 准备工作
- 准备一个 HTML 文件, 在其
body
中引入 VUE 模块. 引入模块化的 js 时, 需要设置 type="module"
, 浏览器才能正确识别其为模块化的 js.
- 创建 VUE 程序的应用实例, 控制试图元素
- 准备元素(div), 交给 VUE 控制
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div id="app">
</div> <script type="module"> import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'; createApp({
}).mount('#app'); </script>
|
模块化 JavaScript 是一种代码组织方式, 它允许我们将代码分割成独立的模块, 每个模块都有自己的功能和作用域.
这种方式有助于代码的维护和复用.
这三步准备工作, 是使用 Vue 的必要操作, 是固定步骤.
2). 数据驱动视图
- 准备数据.
- 通过插值表达式渲染页面. 插值表达式的写法:
{{...}}
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div id="app"> <!-- 使用插值表达式将 message 的值渲染到页面上 --> <h1>{{ message }}</h1> </div> <script type="module"> import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'; createApp({ data(){ return{ message: 'Hello Vue' } } }).mount('#app'); </script>
|
插值表达式是一种模板语法, 常见于许多现代前端框架和库中.
插值表达式用于将 JavaScript 表达式的值嵌入到 HTML 模板中, 这种语法允许你将动态数据渲染到静态的 HTML 结构中.
入门案例完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue-快速入门</title> </head> <body> <div id="app"> {{message}} </div>
<script type="module"> import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js' createApp({ data(){ return { message: 'Hello Vue' } } }).mount('#app') </script> </body> </html>
|
核心指令
VUE 的指令是作用在 HTML 标签中带有 v- 前缀的特殊属性.
例如在 <p></p>
标签中使用 VUE 的指令:
1
| <p v-xxx="....">.....</p>
|
指令 |
作用 |
v-for |
列表渲染,遍历容器的元素或者对象的属性 |
v-bind |
为 HTML 标签绑定属性值,如设置 href , css 样式等 |
v-if/v-else-if/v-else |
条件性的渲染某元素,判定为 true 时渲染,否则不渲染 |
v-show` |
根据条件展示某元素,区别在于切换的是 display 属性的值 |
v-model |
在表单元素上创建双向数据绑定 |
v-on |
为 HTML 标签绑定事件 |
v-for
列表渲染, 遍历容器的元素或者对象的属性.
1
| <tr v-for="(item,index) in items" :key="item.id">{{item}}</tr>
|
参数:
- items 为遍历的数组
- item 为遍历出来的元素
- index 为索引/下标,从 0 开始 ;可以省略,省略 index 语法:
v-for = "item in items"
key:
- 作用:给元素添加的唯一标识,便于 vue 进行列表项的正确排序复用,提升渲染性能
- 推荐使用 id 作为 key(唯一),不推荐使用 index 作为 key(会变化,不对应)
注意:遍历的数组,必须在 data 中定义; 要想让哪个标签循环展示多次,就在哪个标签上使用 v-for 指令。
v-bind
动态为 HTML 标签绑定属性值,如设置 href,src,style 样式等。
1 2 3 4 5
| <img v-bind:src="item.image" width="30px">
<img :src="item.image" width="30px">
|
由于之前的插值表达式无法在标签内使用, 因此想在标签内达到插值表达式的效果, 只能只用这个指令.
另外, v-bind 所绑定的数据同插值表达式, 必须在 data 中定义/或基于 data 中定义的数据而来.
v-if
基于条件判断, 来控制创建或移除元素节点(条件渲染). 要么渲染这个元素,要么删除这个元素.
适用于 不频繁切换的场景.
类似于编程语言的流程控制语法, 同理的, 可以配合 v-else-if
/ v-else
进行链式调用条件判断.
1 2 3 4 5 6
| <td> <span v-if="emp.job === '1'">班主任</span> <span v-else-if="emp.job === '2'">讲师</span> <span v-else>其他</span> </td>
|
v-show
类似于 v-if
这两类指令,都是用来控制元素的显示与隐藏的.
区别于 v-if
, 是基于 CSS 样式 display
来控制显示与隐藏. 无论条件是否成立, 都会渲染. 然后才会判断其显示还是隐藏.
适用于 频繁切换显示隐藏的场景.
1 2 3 4 5 6 7 8
| <td> <span v-show="emp.job === '1'">班主任</span> <span v-show="emp.job === '2'">讲师</span> <span v-show="emp.job === '3'">学工主管</span> <span v-show="emp.job === '4'">教研主管</span> <span v-show="emp.job === '5'">咨询师</span> </td>
|
v-model
在表单元素上使用,双向数据绑定。可以方便的 获取 或 设置 表单项数据
1 2
| <input type="text" id="name" v-model="serachForm.name">
|
是指 Vue 中的数据变, 会影响视图中的数据展示 . 视图中的输入的数据变化, 也会影响 Vue 的数据模型 .
注意:v-model 中绑定的变量, 必须在 data 中定义.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <body> <form class="search-form" action="#" method="post"> <input type="text" name="name" placeholder="姓名" v-model="searchEmp.name" /> <select name="gender" v-model="searchEmp.gender"> <option value="">性别</option> <option value="1">男</option> <option value="2">女</option> </select> <select name="job" v-model="searchEmp.job"> <option value="">职位</option> ... <option value="5">咨询师</option> </select>
<button type="submit">查询</button> <button type="reset" class="clear">清空</button> </form>
<script type="module"> import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js' createApp({ data() { return { searchEmp: { name: '', gender: '', job: '' }, empList: [ 表单数据; } ] } } }).mount('#container') </script>
</div>
</body>
|
v-on
为 html 标签绑定事件 (添加事件监听)
1 2 3 4 5
| <input type="button" value="点我一下试试" v-on:click="handle">
<input type="button" value="点我一下试试" @click="handle">
|
定义的 handle 函数,同之前提到的指令, 也需要在 Vue 应用实例创建的时候创建出来,在 methods 定义, 其与 data 平级.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <body>
<div id="container">
<form class="search-form">
<button type="button" @click="search">查询</button> <button type="button" @click="clear">清空</button> </form>
</tbody> </table>
<script type="module"> import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js' createApp({ data() { ...; }, methods: { search() { console.log(this.searchEmp) }, clear() { this.searchEmp = { name: '', gender: '', job: '' } } } }).mount('#container') </script>
</div>
</body>
|
注意: methods 函数中的 this 指向 Vue 实例,可以通过 this 获取到 data 中定义的数据。
完整案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
| <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tlias智能学习辅助系统</title> <style> body { margin: 0; }
.header { display: flex; justify-content: space-between; align-items: center; background-color: #c2c0c0; padding: 20px 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
.header h1 { margin: 0; font-size: 24px; font-weight: bold; }
.header a { text-decoration: none; color: #333; font-size: 16px; }
.search-form { display: flex; align-items: center; padding: 20px; background-color: #f9f9f9; }
.search-form input[type="text"], .search-form select { margin-right: 10px; padding: 10px 10px; border: 1px solid #ccc; border-radius: 4px; width: 26%; }
.search-form button { padding: 10px 15px; margin-left: 10px; background-color: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
.search-form button.clear { background-color: #6c757d; }
.table { min-width: 100%; border-collapse: collapse; }
.table td, .table th { border: 1px solid #ddd; padding: 8px; text-align: center; }
.avatar { width: 30px; height: 30px; object-fit: cover; border-radius: 50%; }
.footer { background-color: #c2c0c0; color: white; text-align: center; padding: 10px 0; margin-top: 30px; }
.footer .company-name { font-size: 1.1em; font-weight: bold; }
.footer .copyright { font-size: 0.9em; }
#container { width: 80%; margin: 0 auto; } </style> </head> <body>
<div id="container"> <div class="header"> <h1>Tlias智能学习辅助系统</h1> <a href="#">退出登录</a> </div>
<form class="search-form"> <input type="text" name="name" placeholder="姓名" v-model="searchEmp.name" /> <select name="gender" v-model="searchEmp.gender"> <option value="">性别</option> <option value="1">男</option> <option value="2">女</option> </select> <select name="job" v-model="searchEmp.job"> <option value="">职位</option> <option value="1">班主任</option> <option value="2">讲师</option> <option value="3">学工主管</option> <option value="4">教研主管</option> <option value="5">咨询师</option> </select> <button type="button" @click="search">查询</button> <button type="button" @click="clear">清空</button> </form>
<table class="table table-striped table-bordered"> <thead> <tr> <th>姓名</th> <th>性别</th> <th>头像</th> <th>职位</th> <th>入职日期</th> <th>最后操作时间</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="(emp, index) in empList" :key="index"> <td>{{ emp.name }}</td> <td>{{ emp.gender === 1 ? '男' : '女' }}</td> <td><img :src="emp.image" alt="{{ emp.name }}" class="avatar"></td> <td> <span v-if="emp.job === '1'">班主任</span> <span v-else-if="emp.job === '2'">讲师</span> <span v-else-if="emp.job === '3'">学工主管</span> <span v-else-if="emp.job === '4'">教研主管</span> <span v-else-if="emp.job === '5'">咨询师</span> </td> <td>{{ emp.entrydate }}</td> <td>{{ emp.updatetime }}</td> <td class="btn-group"> <button class="edit">编辑</button> <button class="delete">删除</button> </td> </tr> </tbody> </table>
<footer class="footer"> <p class="company-name">江苏传智播客教育科技股份有限公司</p> <p class="copyright">版权所有 Copyright 2006-2024 All Rights Reserved</p> </footer>
<script type="module"> import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js' createApp({ data() { return { searchEmp: { name: '', gender: '', job: '' }, empList: [ { "id": 1, "name": "谢逊", "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/4.jpg", "gender": 1, "job": "1", "entrydate": "2023-06-09", "updatetime": "2024-07-30T14:59:38" }, { "id": 2, "name": "韦一笑", "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg", "gender": 1, "job": "1", "entrydate": "2020-05-09", "updatetime": "2023-07-01T00:00:00" }, { "id": 3, "name": "黛绮丝", "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/2.jpg", "gender": 2, "job": "2", "entrydate": "2021-06-01", "updatetime": "2023-07-01T00:00:00" } ] } }, methods: { search() { console.log(this.searchEmp) }, clear() { this.searchEmp = { name: '', gender: '', job: '' } } } }).mount('#container') </script>
</div>
</body> </html>
|
Vue 生命周期
vue 的生命周期 是 vue 对象从创建到销毁的过程.
其完整的生命周期如下图所示:
vue 的生命周期包含 8 个阶段., 每触发一个生命周期事件, 会自动执行一个生命周期方法, 这些生命周期方法也被称为 钩子方法.
状态 |
阶段周期 |
beforeCreate |
创建前 |
created |
创建后 |
beforeMount |
挂载前 |
mounted |
挂载完成 |
beforeUpdate |
更新前 |
updated |
更新后 |
beforeDestroy |
销毁前 |
destroyed |
销毁后 |
其中我们需要重点关注的是 mounted,其他的我们了解即可。
mounted
挂载完成,Vue 初始化成功,HTML 页面渲染成功。以后我们一般用于页面初始化自动的 ajax 请求后台数据
那我们要想在页面加载完毕,就查询出员工列表,就可以在 mounted 钩子函数中,发送异步请求查询员工数据了。
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| methods: { async search() { const result = await axios.get(`https://web-server.itheima.net/emps/list?name=${this.searchForm.name}&gender=${this.searchForm.gender}&job=${this.searchForm.job}`); this.empList = result.data.data; }, clear() { this.searchForm= { name: '', gender: '', job: '' } this.search(); } }, mounted() { this.search(); } }).mount('#container')
|