1. Vue 概念及创建实例
<body><!-- 创建Vue实例,初始化渲染1. 准备容器 (Vue所管理的范围)2. 引包 (开发版本包 / 生产版本包) 官网3. 创建实例4. 添加配置项 => 完成渲染
--><div id="app"><h1>{{msg}}</h1><a href="#">{{num}}</a></div><!-- Vue是一个用于构建用户界面的渐进式框架构建用户界面 -- 基于数据动态渲染出用户看到的页面渐进式 -- 循序渐进框架 -- 一套完整的项目解决方案,提升开发效率--><!-- 引入的是开发版本包 - 包含完整的注释和警告 --><script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script><script>// 创建Vue实例 new Vue()const app = new Vue({// el 指定挂载点,选择器指定控制的是哪个盒子el: '#app',// data 提供数据data: {msg: 'hello world',num: 100}})</script></body>

2. 插值表达式
<body><!-- 插值表达式:Vue的一种模板语法作用:利用表达式进行插值,将数据渲染页面中语法:{{ 表达式 }}表达式:是可以被求值的代码,JS引擎会将其计算出一个结果注意点:1. 使用的数据要存在2. 支持的是表达式,不是语句 if for3. 不能在标签属性中使用 {{ }}
--><div id="app"><!-- 插值表达式 -- 正确使用 --><h3>{{ msg }}</h3><p>{{ num }}</p><p>{{ `num值为${num}` }}</p><p>{{ num + 1 }}</p><p>{{ num > 10 ? '大于10' : '小于等于10' }}</p><p>{{ obj.name }}</p><p>{{ arr[2] }}</p><!-- 错误使用 --><!-- 1. 数据不存在 --><!-- <p>{{ price }}</p> --><!-- 2. 插入语句 --><!-- <p>{{ if(num>10) {console.log('num大于10')} }}</p> --><!-- 3. 在标签属性中使用 --><!-- <p title="{{ num }}"></p> --></div><script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script><script>new Vue({el: '#app',data: {msg: 'Hello World',num: 20,obj: {name: 'Tom',age: 18},arr: [1, 5, 7, 2, 45, 89]}})</script></body>

3. 响应式特性
<body><!-- 数据的响应式处理 → 响应式:数据变化,视图自动更新聚焦于数据 → 数据驱动视图使用 Vue 开发,关注业务的核心逻辑,根据业务修改数据即可--><div id="app"><h3>在一个插值表达式中引用多个 data 属性</h3><p>+拼接 {{name + ' ' + age}}</p><p>模板字符串 {{ `${name} ${age}` }}</p></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {name: 'Tom',age: 18,}})</script></body>

4. Vue 指令

4.1 v-html v-text
<body><!-- Vue 指令指令就是带有 v- 前缀 的特殊 属性,不同属性 对应 不同的功能学习不同指令 → 解决不同业务场景需求动态解析标签:v-html = "表达式 " → 动态设置元素 innerHTML--><!-- v-html 相当于 innerHTML,识别标签 --><!-- v-text 相当于 innerText,不识别标签,把标签当成普通字符串 --><div id="app"><div v-html="str"></div><div v-html="str1">html超链接</div><div v-text="str1">text超链接</div></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {str: 'Hello',str1: '<a href="#">超链接</a>'}})</script></body>

4.2 v-show v-if
<!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><style>.box {width: 200px;height: 100px;line-height: 100px;margin: 10px;border: 3px solid #000;text-align: center;border-radius: 5px;box-shadow: 2px 2px 2px #ccc;}</style>
</head><body><!-- v-show 底层原理:切换 css 的 display: none 来控制显示隐藏场景:频繁切换显示隐藏的场景v-if 底层原理:根据 判断条件 控制元素的 创建 和 移除(条件渲染)场景:要么显示,要么隐藏,不频繁切换的场景--><div id="app"><div class="box" v-show="blF">我是v-show控制的盒子</div><div class="box" v-if="blF">我是v-if控制的盒子</div></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {blT: true,blF: false}})</script></body></html>

4.3 v-else v-else-if
<body><!-- v-else v-else-if作用:辅助 v-if 进行判断渲染注意:需要紧挨着 v-if 一起使用--><div id="app"><p v-if="gender === 0">性别:♂ 男</p><p v-else>性别:♀ 女</p><hr><p v-if="score >= 90">成绩评定A: 奖励电脑一台</p><p v-else-if="score >= 70">成绩评定B: 奖励周末郊游</p><p v-else-if="score >= 60">成绩评定C: 奖励零食礼包</p><p v-else>成绩评定D: 惩罚一周不能玩手机</p></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {gender: 0,score: 99}})</script></body>

4.4 v-on
4.4.1 内联语句
4.4.2 无参函数
<!-- v-on1. 作用:注册事件 = 添加监听 + 提供处理逻辑2. 语法:v-on:事件名 = "内联语句"v-on:事件名 = "methods中的函数名"3. 简写:@事件名 = "内联语句"4. 注意:methods函数内的 this 指向 Vue 实例
--><body><div id="app"><!-- 1. 内联语句 --><!-- <button v-on:click="num--" v-show="num>1">-</button><span>{{ num }}</span><button @click="num++">+</button> --><!-- 2. 无参函数 --><!-- 需要传参必须写(), 无参函数()有无不影响界面效果 --><button v-on:click="reduce()" v-show="num>1">-</button><span>{{ num }}</span><button @click="add">+</button></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><!-- <script src="lib/vue.js"></script> --><script>const app = new Vue({el: '#app',data: {num: 5},// 封装函数的配置项methods: {add() { this.num++ },reduce() { this.num-- }}})</script>
</body>

4.4.3 案例 - 点击切换隐藏
<body><div id="app"><button @click="fn">切换显示隐藏</button><h1 v-show="flag">黑马程序员</h1></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {flag: true},methods: {fn() { this.flag = !this.flag }}})</script></body>

4.4.4 有参函数 案例 - 小黑自动售货机
<!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><style>.box {border: 3px solid #000000;border-radius: 10px;padding: 20px;margin: 20px;width: 200px;}h3 {margin: 10px 0 20px 0;}p {margin: 20px;}</style>
</head><body><div id="app"><div class="box"><h3>小黑自动售货机</h3><!-- v-bind:disabled="balance>0?false:true" --><button @click="fn(5)" v-bind:disabled="flag">可乐5元</button><button @click="fn(10)" v-bind:disabled="flag">咖啡10元</button><button @click="fn(8)" v-bind:disabled="flag">牛奶8元</button></div><p>银行卡余额:{{balance}}元</p></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {balance: 100,// data 对象的属性初始化时不能直接引用其他属性,因为它们还没有被定义。// flag: this.balance > 0 ? false : true},// 计算属性computed: {flag() {return this.balance <= 0;}},methods: {fn(price) {// this.balance = this.balance - price// this.balance -= priceif (this.balance >= price) {this.balance -= price;} else {alert('余额不足');}}}})</script>
</body></html>

4.5 v-bind
<body><div id="app"><!-- v-bind:src => 可简写为 :src作用:动态的设置html的标签属性--><img v-bind:alt="msg"><img :src="url"></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {msg: '图片',url: 'imgs/10-01.png'}})</script>
</body>

案例图片切换 - 波仔学习之旅
<body><div id="app"><!-- <button @click="reduce">上一页</button> --><button @click="index--" v-show="index>0">上一页</button><div><!-- <img src="imgs/11-00.gif" alt=""> --><img alt="#" :src="imgs[index]"></div><!-- <button @click="add">下一页</button> --><button @click="index++" v-show="index<imgs.length-1">下一页</button></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {imgs: ['imgs/11-00.gif','imgs/11-01.gif','imgs/11-02.gif','imgs/11-03.gif','imgs/11-04.png','imgs/11-05.png'],index: 0,},/* methods: {add() {this.index++},reduce() {this.index--}} */})</script>
</body>

4.6 v-for
<!-- v-for1. 作用:基于数据循环,多次渲染整个元素 → 数组(重要)、对象、数字...2. 遍历数组语法:v-for = "(item, index) in 数组" ➢ item 每一项, index 下标➢ 省略 index: v-for = "item in 数组"
--><body><div id="app"><!-- <h3>小黑水果店</h3> --><!-- 数组 --><ul><li v-for="(item,index) in list">{{item}} -- {{index}}</li><li v-for="(item) in list">{{item}}</li></ul><!-- 字符串 --><ul><li v-for="(item) in str">{{item}}</li></ul><!-- 对象 --><p v-for="(value,key,index) in obj">{{value}} -- {{key}} -- {{index}}</p></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {list: ['Tom', 'Jerry', 'Rose'],str: 'Hi',obj: {name: 'Taylor',age: 19,}}})</script>
</body>

案例图书管理 - 小黑的书架
<!-- 图书管理案例 - 小黑的书架 --><body><div id="app"><h3 style="margin-left: 30px;">小黑的书架</h3><ul><!-- <li><span>《红楼梦》</span><span>曹雪芹</span><button>删除</button></li> --><li v-for="(item) in booksList"><span>{{item.name}}</span><span>{{item.author}}</span><button @click="del(item.id)">删除</button></li></ul></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {booksList: [{ id: 1, name: '《红楼梦》', author: '曹雪芹' },{ id: 2, name: '《西游记》', author: '吴承恩' },{ id: 3, name: '《水浒传》', author: '施耐庵' },{ id: 4, name: '《三国演义》', author: '罗贯中' }]},methods: {del(id) {// console.log(id)// 用 filter 根据 id 从数组中删除对应项this.booksList = this.booksList.filter((item) => {return item.id !== id})}}})</script>
</body>

v-for 中的 key
<!-- v-for 中的 key语法:key属性 = "唯一标识"作用:给列表项添加的唯一标识。便于Vue进行列表项的正确排序复用。注意点:1. key 的值只能是 字符串 或 数字类型2. key 的值必须具有 唯一性3. 推荐使用 id 作为 key(唯一),不推荐使用 index 作为 key(会变化,不对应)不加 keyv-for 的默认行为会尝试 原地修改元素 (就地复用)
--><body><div id="app"><h3 style="margin-left: 30px;">小黑的书架</h3><ul><!-- <li v-for="(item) in booksList"> --><li v-for="(item) in booksList" :key="item.id"><span>{{item.name}}</span><span>{{item.author}}</span><button @click="del(item.id)">删除</button></li></ul></div><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {booksList: [{ id: 1, name: '《红楼梦》', author: '曹雪芹' },{ id: 2, name: '《西游记》', author: '吴承恩' },{ id: 3, name: '《水浒传》', author: '施耐庵' },{ id: 4, name: '《三国演义》', author: '罗贯中' }]},methods: {del(id) {this.booksList = this.booksList.filter((item) => {return item.id !== id})}}})</script>
</body>

4.7 v-model
<body><div id="app"><!-- v-model 可以让数据和视图,形成双向数据绑定(1) 数据变化,视图自动更新(2) 视图变化,数据自动更新可以快速[获取]或[设置]表单元素的内容语法: v-model = '变量'-->账户:<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>

5. 综合案例 - 小黑记事本
<!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="./css/index.css" /><title>记事本</title>
</head><body><!-- 主体区域 --><section id="app"><!-- 输入框 --><header class="header"><h1>小黑记事本</h1><input placeholder="请输入任务" class="new-todo" v-model="todo" /><button class="add" @click="add">添加任务</button></header><!-- 列表区域 --><section class="main"><ul class="todo-list"><!-- 1. 列表渲染 --><li class="todo" v-for="(item,index) in list" :key="item.id"><div class="view"><span class="index">{{index+1}}.</span> <label>{{item.txt}}</label><button class="destroy" @click="del(item.id)"></button></div></li></ul></section><!-- 统计和清空 --><footer class="footer"><!-- 统计 --><!-- <span class="todo-count">合 计:<strong> 1 </strong></span> --><span class="todo-count">合 计:<strong> {{list.length}} </strong></span><!-- 清空 --><button class="clear-completed" @click="reset" v-show="list.length>0">清空任务</button></footer></section><!-- 底部 --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script>const app = new Vue({el: '#app',data: {todo: '',list: [{ id: 1, txt: '敲代码' },{ id: 2, txt: '删代码' },{ id: 3, txt: '改代码' }]},methods: {// 2. 添加功能add() {/* if (this.todo.trim().length > 0) {this.list.unshift({id: +new Date(),txt: this.todo})// console.log(this.list[0].id)this.todo = ''} */if (this.todo.trim() === '') {alert('请输入任务内容')return}this.list.unshift({id: +new Date(),txt: this.todo})this.todo = ''},// 3. 删除功能del(id) {this.list = this.list.filter(item => item.id !== id)},// 4. 清空reset() {this.list = []}}})</script>
</body>
<!-- 功能总结:1. 列表渲染: v-for key 的设置 {{ }} 插值表达式2. 删除功能: v-on 调用传参 filter 过滤 覆盖修改原数组3. 添加功能: v-model 绑定 unshift 修改原数组添加4. 底部统计 和 清空数组.length累计长度覆盖数组清空列表v-show 控制隐藏
--></html>

6. 作业
6.1 哔哩哔哩首页
<!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>bilibili-干杯~~~</title><!-- 引入favicon图标 --><link rel="shortcut icon" href="favicon.ico" type="image/x-icon"><!-- 引入css文件 --><link rel="stylesheet" href="./css/index.css"><!-- 引入字体图标文件 --><link rel="stylesheet" href="./fonts/iconfont.css">
</head><body><div id="app"><!-- 头部模块 --><header class="suspension"><div class="m-navbar"><!-- logo --><a href="#" class="logo"><i class="iconfont Navbar_logo"></i></a><!-- 右侧 --><div class="right"><a href="#" class="search"><i class="iconfont ic_search_tab"></i></a><a href="#" class="face"><img src="./images/login.png" alt=""></a><div class="app-btn"><img src="./images/download.png" alt=""></div></div></div><div class="channel-menu"><div class="tabs"><!-- 很宽的盒子 --><div class="tabs-list"><a href="#">首页</a><a href="#">动画</a><a href="#">番剧</a><a href="#">果蔬</a><a href="#">音乐</a><a href="#">舞蹈</a><a href="#">鬼畜</a><a href="#">吹鬼</a><!-- 红色线 --><div class="line"></div></div></div><!-- 下拉箭头 --><div class="after"><i class="iconfont general_pulldown_s" @click="isShow"></i></div></div></header><!-- 频道下拉模块 --><div class="tabs-dropdown" v-show="flag"><div class="tabs-wrap"><span v-for="(item) in channelList">{{item}}</span><!-- <span>动画</span><span>番剧</span><span>国创</span><span>音乐</span><span>舞蹈</span><span>游戏</span><span>科技</span><span>运动</span><span>汽车</span><span>生活</span><span>美食</span><span>动物圈</span> --><!-- ''''''' --></div><div class="close-wrap"><span @click="isShow">收起︿</span></div></div><!-- 主体部分 --><div class="m-home"><div class="video-list"><!-- 视频卡片模板 --><a href="#" class="video-item" v-for="(item) in videoList"><div class="card"><img :src=item.img><!-- 播放量 --><div class="count"><span><i class="iconfont icon_shipin_bofangshu"></i>{{item.views}}<!-- item.views --></span><span><i class="iconfont icon_shipin_danmushu"></i>{{item.commonet}}</span></div></div><p class="title ellipsis-2"><!-- 黑马程序员前端React入门到实战视频教程,从react18+hooks核心基础到企业级项目开发实战(B站评论、极客园项目等)及大厂面试全通关 -->{{item.title}}</p></a></div></div><!-- 底部模块 --><footer class="app"><div class="btn-app"><i class="iconfont Navbar_logo"></i>打开App,看你感兴趣的视频</div></footer></div><script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script><!-- <script src="./js/index.js"></script> --><script>// TODO:阅读代码,根据提供的数据,实现目标效果// DATA字段说明/*** channelList 频道列表* videoList 视频列表* title 视频标题* views 播放量* commonet 评论量* img 封面图片*//* 具体需求如下:频道列表展开收起:点击下拉箭头,显示频道列表,点击收起,隐藏频道列表频道渲染:根据提供数据,循环渲染出每个频道播放列表渲染:根据提供数据,循环渲染出每个视频的信息*/const app = new Vue({el: "#app",data: {channelList: ["首页","动画","番剧","国创","音乐","舞蹈","游戏","科技","运动","汽车","生活","美食","知识","动物圈","鬼畜","时尚娱乐影视","纪录片","电影","电视剧","直播","相簿","课堂",],videoList: [{title:"黑马程序员前端React入门到实战视频教程,从react18+hooks核心基础到企业级项目开发实战(B站评论、极客园项目等)及大厂面试全通关",views: "110.6W",commonet: "2.3万",img: "https://i0.hdslb.com/bfs/archive/4ba435e67fa208ce7a5343c0fc2cd454d8cc50fc.jpg@480w_270h_1c",},{title:"黑马程序员前端JavaScript入门到精通全套视频教程,javascript核心进阶ES6语法、API、js高级等基础知识和实战教程",views: "238.4W",commonet: "8.9万",img: "https://i1.hdslb.com/bfs/archive/7cbcf700e3950f40dab97b5e57c8581733fdad22.jpg@480w_270h_1c",},{title:"Java八股文面试题视频教程,Java面试八股文宝典(含阿里、腾迅大厂java面试真题,java数据结构,java并发,jvm等最新java面试真题)",views: "87.5W",commonet: "1.4万",img: "https://i1.hdslb.com/bfs/archive/3c0dbdf9863a9e21d8ea5c50892b01db1268a268.jpg@480w_270h_1c",},{title:"黑马程序员2023新版JavaWeb开发教程,实现javaweb企业开发全流程(涵盖Spring+MyBatis+SpringMVC+SpringBoot等)",views: "231.6W",commonet: "8.2万",img: "https://i1.hdslb.com/bfs/archive/81c2b09fea6a978a169eeb3fde028066751e06e5.jpg@480w_270h_1c",},{title:"黑马程序员Node.js全套入门教程,nodejs新教程含es6模块化+npm+express+webpack+promise等_Nodejs实战案例详解",views: "209.6W",commonet: "5.5万",img: "https://i2.hdslb.com/bfs/archive/a35e28d321c55c783526b2382431409935ddfb9f.jpg@480w_270h_1c",},{title:"2023新版数据结构与算法Java视频教程(上篇),java高级程序员必学的数据结构与算法",views: "54.6W",commonet: "1万",img: "https://i1.hdslb.com/bfs/archive/8dae32b310561144385867468a39b3f7cab1ba24.jpg@480w_270h_1c",},{title: "黑马程序员人工智能教程_10小时学会图像处理OpenCV入门教程",views: "71W",commonet: "1.8万",img: "https://i0.hdslb.com/bfs/archive/c6f5409bb52de12370b0cd73d98d0f1dd2019f9e.jpg@480w_270h_1c",},{title:"黑马程序员全套Python教程_Python基础入门视频教程,零基础小白自学Python入门教程",views: "157W",commonet: "4.8万",img: "https://i0.hdslb.com/bfs/archive/213b14bfbdbf54248a3f5fa742cb9f9c8f684274.png@480w_270h_1c",},],flag: true,},methods: {isShow() {this.flag = !this.flag;},},});</script>
</body></html>

6.2 Boss 直聘技能选择 - 二次开发
<!DOCTYPE html>
<html><head><title>Boss直聘技能选择</title><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="./css/index.css">
</head><body><div id="app"><h2><span class="logo-head"></span></h2><div class="skill-tip"><h3>拥有技能</h3><p>请选择技能标签,被选中的标签将突出展示给BOSS</p></div><div class="skill-wrap"><div class="title">自定义标签</div><div class="add-wrap"><input type="text" class="tip" placeholder="请输入关键词" v-model="newSkill" /><button class="add-btn" @click="add">添加</button></div></div><ul class="skill-wrap select"><div class="title">已选</div><!-- <li>html5 <span>x</span></li> --><li v-for="(item) in sT()" @click="item.select = !item.select">{{item.skillName}} <span>x</span></li></ul><ul class="skill-wrap"><div class="title">可选</div><!-- <li>css3</li> --><li v-for="(item) in sF()" @click="item.select = !item.select">{{item.skillName}}</li></ul></div><script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script><!-- <script src="./js/index.js"></script> --><script>// TODO:阅读代码,根据提供的数据,实现目标效果// DATA字段说明/*** skillList 技能列表* skillName 技能名称* select 已选择*//* 具体需求如下:渲染数据:将提供的数据绑定到页面对应的位置已选标签:数据中select字段为true的数据对应显示已选列表中,点击标签时更改为可选可选标签:数据中select字段为false的数据对应显示可选列表中,点击标签时更改为已选添加自定义标签:输入框内容为空时,点击添加,不处理当输入框内容不为空时,点击添加,在已选列表中新增标签新增标签后,清空输入框内容新增的自定义标签可以点击切换可选和已选的状态*/const app = new Vue({el: '#app',data: {skillList: [{skillName: "html5",select: true,},{skillName: "css3",select: true,},{skillName: "javascript",select: true,},{skillName: "webapi",select: true,},{skillName: "ajax",select: true,},{skillName: "git",select: true,},{skillName: "echarts",select: true,},{skillName: "node",select: true,},{skillName: "vue",select: true,},{skillName: "微信小程序",select: false,},{skillName: "uni-app",select: false,},{skillName: "react",select: false,},],newSkill: "",},methods: {sT() {return this.skillList.filter((item) => item.select === true);},sF() {return this.skillList.filter((item) => item.select === false);},add() {if (this.newSkill.trim() === "") {alert("请输入有效标签");return;}this.skillList.push({skillName: this.newSkill,select: true,});this.newSkill = "";},},});</script>
</body></html>

6.3 12306 订单详情 - 变形题
<!DOCTYPE html>
<html><head><title>12306订单详情</title><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="./css/index.css">
</head><body><div id="app" :style="showStyle"><h1>订单详情</h1><div class="container"><!-- 车次信息 --><div class="ticket-info"><div class="start"><div class="time">{{orderInfo.startTime}}</div><div class="origin">{{orderInfo.origin}}<span>></span></div></div><div class="train-info"><div class="train-number">{{orderInfo.trainNumber}}<span>></span></div><div class="station-type">{{orderInfo.stationType === 1?'始发站':'经停站'}}</div><div class="train-duration">历时{{orderInfo.duration}}</div></div><div class="end"><div class="time">{{orderInfo.endTime}}</div><div class="destination">{{orderInfo.destination}}<span>></span></div></div></div><!-- 发车时间 --><div class="train-date"><span class="start-date">发车时间:{{orderInfo.trainDate}}</span><span class="expiration-date">车票当日当次有效</span></div><!-- 改签退票 --><div class="btn-wrap"><button :disabled="!orderInfo.rebook" @click="reOrCan('改签')">改签</button><span>|</span><button :disabled="!orderInfo.cancellation" @click="reOrCan('退票')">退票</button></div><!-- 乘车人列表 --><div class="passenger-list"><!-- <div class="passenger-info"><h3 class="passenger"><div class="passenger-name">张三 <span class="passenger-type">成人票</span></div><div class="seat-info"><span class="seat-type">过道</span>二等座 04车 11B号</div></h3><div class="seat-price"><div class="passenger-passport">中国居民身份证</div><div class="price">¥263</div></div><div class="status"><div class="ticket-status">已出站</div><div class="illustrate">退改说明</div></div></div> --><div class="passenger-info" v-for="(passenger) in orderInfo.passengers"><h3 class="passenger"><div class="passenger-name">{{passenger.pname}} <span class="passenger-type">{{passenger.isAdult ? '成人票':'儿童票'}}</span></div><div class="seat-info"><spanclass="seat-type">{{seatType(passenger.seatType)}}</span>{{passenger.seat}}</div></h3><div class="seat-price"><div class="passenger-passport">中国居民身份证</div><div class="price">¥{{passenger.price}}</div></div><div class="status"><div class="ticket-status">已出站</div><div class="illustrate">退改说明</div></div></div></div></div><div class="tip">🔔 订单信息查询有效期限为30日</div></div><script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script><!-- <script src="./js/index.js"></script> --><script>// TODO:阅读代码,根据提供的订单信息数据,通过学习的Vue指令将页面渲染成目标效果// DATA:数据字段说明/*** startTime: 发车时间* endTime: 到站时间* origin: 发车站* destination:目的地* trainNumber:车次* trainDate:发车日期* stationType:车站类型(1为始发站,2为经停站)* duration:历时* rebook:能否改签* cancellation:能否退票* passengers:乘车人列表* pid:乘车人ID* pname:乘车人姓名* isAdult:是否成年* seat:座位* price:票价* seatType:作为类型(1是靠窗,2是中间,3是过道)*/const app = new Vue({el: "#app",data: {// 防止渲染闪烁showStyle: "display:block;",orderInfo: {startTime: "14:11",endTime: "17:40",origin: "西安北",destination: "成都东",trainNumber: "D1937",trainDate: "2023.09.30 星期六",stationType: 2,duration: "3时29分",// rebook:能否改签 能改签t 按钮不禁用frebook: false,cancellation: true,passengers: [{pid: "0001",pname: "王大锤",isAdult: true,seat: "二等座 04车 11A号",price: 263,seatType: 1,},{pid: "0002",pname: "李二狗",isAdult: false,seat: "二等座 04车 11B号",price: 263,seatType: 2,},{pid: "0003",pname: "张三疯",isAdult: true,seat: "二等座 04车 11C号",price: 263,seatType: 3,},],},},methods: {seatType(num) {switch (num) {case 1:return "靠窗";/* case 2:return "中间"; */case 3:return "过道";}},reOrCan(msg) {// console.log(11);if (msg === "改签" && this.orderInfo.rebook === true) {alert(`${msg}成功`);} else if (msg === "退票" && this.orderInfo.cancellation === true) {alert(`${msg}成功`);}},},});</script>
</body></html>
