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 for
3. 不能在标签属性中使用 {{ }}
-->
<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-on
1. 作用:注册事件 = 添加监听 + 提供处理逻辑
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 -= price
if (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-for
1. 作用:基于数据循环,多次渲染整个元素 → 数组(重要)、对象、数字...
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(会变化,不对应)
不加 key
v-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,index) in videoList" :key="index">
<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,index) in sT()" :key="index" @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,index) in sF()" :key="index" @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);
return this.skillList.filter((item) => item.select);
},
sF() {
// return this.skillList.filter((item) => item.select === false);
return this.skillList.filter((item) => !item.select);
},
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="showMsg('改签成功')">改签</button>
<span>|</span>
<button :disabled="!orderInfo.cancellation" @click="showMsg('退票成功')">退票</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" :key="passenger.pid">
<h3 class="passenger">
<div class="passenger-name">
{{passenger.pname}} <span class="passenger-type">{{passenger.isAdult ? '成人票':'儿童票'}}</span>
</div>
<div class="seat-info">
<!-- <span class="seat-type">{{seatType(passenger.seatType)}}</span> -->
<span class="seat-type" v-if="passenger.seatType!==2">
{{passenger.seatType===1?'靠窗':'过道'}}</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 按钮不禁用f
rebook: 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 === "改签") {
alert(`${msg}成功`);
} else if (msg === "退票") {
alert(`${msg}成功`);
}
}, */
showMsg(msg) {
alert(msg)
}
},
});
</script>
</body>
</html>
