- 掌握 HTML,CSS,JavaScript,AJAX 基础知识
- 选用 VSCode 作为开发工具
- 课程安排:基础 → 本地应用 → 网络应用 → 综合应用
基础
Vue 简介
- JavaScript 框架
- 简化 Dom 操作
- 响应式数据驱动
第一个 Vue 程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>VueCode</title>
</head>
<body>
<!-- 3.使用简洁的模板语法把数据渲染到页面上 -->
<div id="app">
{{ message }}
</div>
<!-- 1.导入开发版本的 Vue.js -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- 2.创建 Vue 实例对象 -->
<script>
var app = new Vue({
el:"#app", // el:挂载点
data:{ // data:数据对象
message:"Hello Vue!"
}
})
</script>
</body>
</html>
el:挂载点
- 作用:设置 Vue 实例挂载(管理)
- Vue 会管理 el 选项命中的元素及其内部的后代元素
- 可以使用其他的选择器,但建议使用 ID 选择器
- 可以使用其他的双标签,但不能使用 <html> 和 <body>
<body>
1.{{ message }}
<div id="app" class="app">
2.{{ message }}
<span>
3.{{ message }}
</span>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app", // ID 选择器
// el:".app", // Class 选择器
// el:"div", // 标签选择器
data:{
message:"挂载点"
}
})
</script>
</body>
data:数据对象
- 作用:定义 Vue 中用到的数据
- data 中可以写复杂类型的数据
- 渲染复杂类型数据时,遵守js的语法即可
<body>
<div id="app">
{{ message }}
<h2> {{ school.name }} {{ school.mobile }} </h2>
<ul>
<li> {{ campus[0] }} </li>
<li> {{ campus[1] }} </li>
<li> {{ campus[2] }} </li>
<li> {{ campus[3] }} </li>
</ul>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"数据对象",
school:{
name:"黑马程序员",
mobile:"000-000-0000"
},
campus:["北京校区","上海校区","广州校区","深圳校区"]
}
})
</script>
</body>
本地应用
v-text 指令:设置标签的文本值(textContent)
<body>
<div id="app">
<!-- 默认写法会替换全部内容,使用插值表达式可以替换指定内容 -->
<h2 v-text="message"> 设置标签的文本值 </h2>
<!-- 内部支持写表达式,比如字符串拼接 -->
<h2> {{ message+':' }} 设置标签的文本值 </h2>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"文本值"
}
})
</script>
</body>
v-html 指令:设置标签的 innerHTML
<body>
<div id="app">
<!-- v-html 指令如果内容有 html 结构会被解析为标签 -->
<p v-html="message"></p>
<!-- v-text 指令无论内容是什么都会解析为文本 -->
<p v-text="message"></p>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
// message:"文本值"
message:"<a href='https://www.baidu.com/'>百度</a>"
}
})
</script>
</body>
v-on 指令:为元素绑定事件
<body>
<div id="app">
<input type="button" value="单击事件" v-on:click="remindInfo" />
<input type="button" value="双击事件" v-on:dblclick="remindInfo" />
<input type="button" value="鼠标移入事件" v-on:mouseenter="remindInfo" />
<!-- 完整写法是 v-on:事件,可以简写为 @事件 -->
<h1 @click="changeFood"> {{ food }} </h1>
<!-- 事件后面加上 .修饰符,可以对事件进行限制 -->
<input type="text" @keyup.enter="sayHi" />
<input type="button" value="点击" @click="getData(666,'老铁')" />
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
food:"西兰花炒蛋"
},
// 绑定的方法定义在 methods 中
methods:{
remindInfo:function(){
alert("显示提示信息");
},
// 方法内部通过 this 关键字可以访问定义在 data 中的数据
changeFood:function(){
// console.log(this.food);
this.food+="好好吃!";
},
// 方法写成函数调用的形式,可以定义形参接收传入的实参
getData:function(p1,p2){
console.log(p1);
console.log(p2);
},
sayHi:function(){
alert("Hi");
}
}
})
</script>
</body>
v-bind 指令:为元素绑定属性
<body>
<div id="app">
<img v-bind:src="imgSrc" v-bind:title="imgTitle+'-logo'">
<!-- 完整写法是 v-bind:属性,可以简写为 :属性 -->
<img :src="imgSrc" :title="imgTitle+'-logo'" :class="isActive?'active':''" @click="toggleActive">
<!-- 需要动态的增删 class 建议使用对象的方式 -->
<img :src="imgSrc" :title="imgTitle+'-logo'" :class="{active:isActive}" @click="toggleActive">
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
imgSrc:"http://www.itheima.com/images/logo.png",
imgTitle:"黑马程序员",
isActive:false
},
methods:{
toggleActive:function(){
this.isActive = !this.isActive;
}
}
})
</script>
</body>
v-show 指令:切换元素显示状态(修改 display)
<body>
<div id="app">
<!-- 数据改变之后,对应元素的显示状态会同步更新 -->
<input type="button" value="切换显示状态" @click="changeIsShow" />
<input type="button" value="累加年龄" @click="addAge" />
<!-- v-show 指令的内容都会解析为布尔值,值为 true 元素显示,值为 false 元素隐藏 -->
<img src="http://www.itheima.com/images/logo.png" v-show="isShow">
<img src="http://www.itheima.com/images/logo.png" v-show="age>=18">
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
isShow:false,
age:16
},
methods:{
changeIsShow:function(){
this.isShow = !this.isShow;
},
addAge:function(){
this.age++;
}
}
})
</script>
</body>
v-if 指令:切换元素显示状态(操纵 dom 元素)
<body>
<div id="app">
<input type="button" value="切换显示状态" @click="toggleIsShow" />
<!-- v-if 指令的值为 true 则元素存在于 dom 树中,值为 false 则元素从 dom 树中移除 -->
<p v-if="isShow">我是一个段落。</p>
<!-- v-show 指令适用于频繁切换元素,v-if 指令则相反,前者切换消耗小 -->
<p v-show="isShow">我是一个段落。</p>
<h2 v-if="temperature>=35">热死了!</h2>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
isShow:false,
temperature:40
},
methods:{
toggleIsShow:function(){
this.isShow = !this.isShow;
}
}
})
</script>
</body>
v-for 指令:根据数据生成列表结构
<body>
<div id="app">
<ul>
<!-- 语法是 (item,index) in data,其中 item 是每项数据,index 是索引 -->
<li v-for="(item,index) in arr"> 黑马程序员校区:{{ index+1 }} {{ item }} </li>
</ul>
<input type="button" value="添加数据" @click="add" />
<input type="button" value="移除数据" @click="remove" />
<!-- 数组经常和 v-for 指令结合使用,数组长度的更新会同步到页面上 -->
<p v-for="item in vegetables" :title="item.name"> {{ item.name }} </p>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
arr:["北京","上海","广州","深圳"],
vegetables:[
{name:"西兰花炒蛋"},
{name:"糖醋排骨"}
]
},
methods:{
add:function(){
this.vegetables.push({name:"鱼香肉丝"});
},
remove:function(){
this.vegetables.shift();
}
}
})
</script>
</body>
v-model 指令:获取和设置表单元素的值(双向数据绑定)
<body>
<div id="app">
<!-- 绑定的数据会和表单元素的值相关联,同步更新 -->
<input type="text" v-model="message" @keyup.enter="getMessage"/>
<input type="button" value="修改" @click="setMessage" />
<p> {{ message }} </p>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"黑马程序员"
},
methods:{
getMessage:function(){
alert(this.message);
},
setMessage:function(){
this.message = "酷丁鱼";
}
}
})
</script>
</body>
- 实现【计数器】功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>计数器</title>
</head>
<body>
<div id="app">
<button @click="sub"> - </button>
<!-- 3.使用 v-text 指令:将 num 设置给 span 标签 -->
<span> {{ num }} </span>
<!-- 4.使用 v-on 指令:将 add, sub 分别绑定给 +, - 按钮 -->
<button @click="add"> + </button>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
// 1.data 中定义数据:num
data:{
num:1
},
// 2.methods 中定义方法:add(递增), sub(递减)
methods:{
// 小于 10 递增,否则提示信息
add:function(){
console.log("add");
if(this.num<10)
this.num++;
else
alert("别点了,已经是最大值了!");
},
// 大于 0 递减,否则提示信息
sub:function(){
console.log("sub");
if(this.num>0)
this.num--;
else
alert("别点了,已经是最小值了!");
}
}
})
</script>
</body>
</html>
- 实现【图片切换】功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>图片切换</title>
</head>
<body>
<div id="app">
<!-- 3.使用 v-bind 指令:绑定 src 属性 -->
<img :src="imgArr[index]">
<!-- 4.使用 v-on 指令:将 prev, next 分别绑定给 ←, → 按钮 -->
<!-- 5.使用 v-show 指令:切换元素显示状态 -->
<button @click="prev" v-show="index!=0"> ← </button>
<button @click="next" v-show="index!=imgArr.length-1"> → </button>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
// 1.data 中定义数据:imgArr(图片数组), index(图片索引)
data:{
imgArr:[
"https://c.53326.com/d/file/20200519/eay0rqilkgr.jpg",
"https://c.53326.com/d/file/20200519/2u53jnui1ud.jpg",
"https://c.53326.com/d/file/20200519/uux3ter23kl.jpg",
"https://c.53326.com/d/file/20200519/zyul5tjqi3a.jpg",
"https://c.53326.com/d/file/20200519/zcqloqx4lm3.jpg"
],
index:0
},
// 2.methods 中定义方法:prev(上一张), next(下一张)
methods:{
prev:function(){
this.index--;
},
next:function(){
this.index++;
}
}
})
</script>
</body>
</html>
- 实现【记事本】功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>记事本</title>
</head>
<body>
<div id="app">
<h1>小黑记事本</h1>
<!-- 4.使用 v-model 指令:获取用户输入 -->
<!-- 5.使用 v-on 指令:.enter 添加数据 -->
<input autofocus="autofocus" autocomplete="off" placeholder="请输入任务" v-model="inputValue" @keyup.enter="add" />
<ul>
<!-- 3.使用 v-for 指令:生成列表结构 -->
<li v-for="(item,index) in list">
<span> {{ index+1 }}. </span>
<label> {{ item }} </label>
<!-- 6.使用 v-on 指令:点击 × 按钮删除指定内容 -->
<button @click="remove(index)"> × </button>
</li>
</ul>
<!-- 9.使用 v-show 指令:没有数据时,隐藏元素 -->
<p v-show="list.length!=0">
<!-- 7.使用 v-text 指令:统计信息个数 -->
<label> {{ list.length }} items </label>
<!-- 8.使用 v-on 指令:点击 clear 按钮清空所有信息 -->
<button @click="clear"> clear </button>
</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
// 1.data 中定义数据:list(任务列表), inputValue(用户输入)
data:{
list:["写代码","吃饭","睡觉"],
inputValue:""
},
// 2.methods 中定义方法:add(新增任务), remove(移除任务), clear(清空)
methods:{
// 把 inputValue 添加到 list 数组中
add:function(){
this.list.push(this.inputValue);
},
// 根据 index 删除对应的 list 数组元素
remove:function(index){
console.log(index);
this.list.splice(index, 1);
},
// 清空 list 数组
clear:function(){
this.list = [];
}
}
})
</script>
</body>
</html>
网络应用
axios:功能强大的网络请求库
使用 get 或 post 方法即可发送对应的请求
axios.get(地址?key1=value1&key2=value2&...)
.then(function(response){
...
},function(err){
...
})
axios.post(地址,{key1:value1,key2:value2,...)
.then(function(response){
...
},function(err){
...
})
axios 基本使用
<body>
<input type="button" value="get请求" class="get" />
<input type="button" value="post请求" class="post" />
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
/*
接口1:随机笑话
请求地址:https://autumnfish.cn/api/joke/list
请求方法:get
请求参数:num(笑话条数,数字)
响应内容:随机笑话
*/
document.querySelector(".get").onclick = function() {
axios.get("https://autumnfish.cn/api/joke/list?num=3")
// then 方法中的回调函数会在请求成功或失败时触发
.then(function(response){
// 通过回调函数的形参可以获取响应内容或错误信息
console.log(response);
},function(err){
console.log(err);
})
}
/*
接口2:用户注册
请求地址:https://autumnfish.cn/api/user/reg
请求方法:post
请求参数:username(用户名,字符串)
响应内容:注册成功或失败
*/
document.querySelector(".post").onclick = function() {
axios.post("https://autumnfish.cn/api/user/reg",{username:"Jack"})
.then(function(response){
console.log(response);
},function(err){
console.log(err);
})
}
</script>
</body>
axios + vue 基本使用
<body>
<div id="app">
<input type="button" value="按钮" @click="getJoke" />
<p> {{ joke }} </p>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
/*
接口:随机获取一条笑话
请求地址:https://autumnfish.cn/api/joke
请求方法:get
请求参数:无
响应内容:一条笑话
*/
var app = new Vue({
el:"#app",
data:{
joke:"点击按钮,随机获取一条笑话"
},
methods:{
getJoke:function(){
// console.log(this.joke);
// 需要把 this 先保存起来,在回调函数中使用保存的 this 即可
var that = this;
// 网络应用和本地应用的最大区别就是改变了数据来源
axios.get("https://autumnfish.cn/api/joke")
.then(function(response){
// console.log(response);
console.log(response.data);
// axios 回调函数中的 this 已经改变,无法访问到 data 中的数据
// console.log(this.joke);
that.joke = response.data;
},function(err){ })
}
}
})
</script>
</body>
- 实现【天气预报】功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>天气预报</title>
</head>
<body>
<div id="app">
<h1>天气预报</h1>
<!-- 3.使用 v-model 指令:获取用户输入 -->
<!-- 4.使用 v-on 指令:.enter 查询数据 -->
<input autofocus="autofocus" autocomplete="off" placeholder="请输入城市" v-model="city" @keyup.enter="searchWeather" />
<input type="button" value="查询" @click="searchWeather" />
<br />
<!-- 6.使用 v-on 指令:点击 4 个城市查询数据 -->
<small @click="changeCity('北京')"> 北京 </small>
<small @click="changeCity('上海')"> 上海 </small>
<small @click="changeCity('广州')"> 广州 </small>
<small @click="changeCity('深圳')"> 深圳 </small>
<!-- 5.使用 v-for 指令:生成 5 天天气信息的数组 -->
<ul>
<li v-for="item in weatherList">
<p> {{ item.date }} </p>
<p> {{ item.type }} | {{ item.low }} ~ {{ item.high }} | {{ item.fengxiang }} </p>
</li>
</ul>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
/*
接口:天气接口
请求地址:http://wthrcdn.etouch.cn/weather_mini
请求方法:get
请求参数:city(查询的城市名称)
响应内容:天气信息
*/
var app = new Vue({
el:"#app",
// 1.data 中定义数据:city(输入城市), weatherList(天气信息的数组)
data:{
city:"",
weatherList:[]
},
// 2.methods 中定义方法:searchWeather(查询天气), changeCity(修改城市)
methods:{
searchWeather:function(){
// console.log("北京");
// console.log(this.city);
var that = this;
axios.get("http://wthrcdn.etouch.cn/weather_mini?city="+this.city)
.then(function(response){
// console.log(response);
// console.log(response.data.data.forecast);
that.weatherList = response.data.data.forecast;
},function(err){ })
},
changeCity:function(city){
this.city = city;
this.searchWeather();
}
}
})
</script>
</body>
</html>
综合应用
- 实现【音乐播放器】功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>音乐播放器</title>
</head>
<body>
<div id="app">
<div class="contanier">
<div class="middle">
<h1>音乐播放器</h1>
</div>
<div class="left_up">
<!-- 1.歌曲搜索 -->
<input type="text" autocomplete="off" v-model="keywords" @keyup.enter="searchMusic" />
<input type="button" value="🔍" @click="searchMusic" />
</div>
<div class="left">
<ul>
<li v-for="item in musicList">
<input type="button" value="🎵" @click="playMusic(item.id)" />
{{ item.name }} -- {{ item.artists[0].name }}
</li>
</ul>
</div>
<div class="right">
<!-- 4.歌曲评论 -->
<dl v-for="item in hotComments">
<img :src="item.user.avatarUrl" />
<dt> {{ item.user.nickname }} </dt>
<dd> {{ item.content }} </dd>
</dl>
</div>
<div class="middle_up">
<!-- 3.歌曲封面 -->
<img :src="musicCover" />
</div>
<div class="right_down">
<!-- 2.歌曲播放 -->
<audio :src="musicUrl" controls autoplay loop></audio>
</div>
</div>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
// 1.data 中定义数据
data:{
keywords:"", // 查询的关键字
musicList:[], // 歌曲数组
musicUrl:"", // 歌曲地址
musicCover:"", // 歌曲封面
hotComments:[], // 歌曲评论
},
// 2.methods 中定义方法
methods:{
/*
接口:歌曲搜索
请求地址:https://autumnfish.cn/search
请求方法:get
请求参数:keywords(查询的关键字)
响应内容:歌曲搜索结果
*/
searchMusic:function(){
var that = this;
// 查询歌曲
axios.get("https://autumnfish.cn/search?keywords="+this.keywords)
.then(function(response){
that.musicList = response.data.result.songs;
},function(err){ })
},
/*
接口:歌曲地址获取
请求地址:https://autumnfish.cn/song/url
请求方法:get
请求参数:id(歌曲编号)
响应内容:歌曲url地址
接口:歌曲封面获取
请求地址:https://autumnfish.cn/song/detail
请求方法:get
请求参数:ids(歌曲编号)
响应内容:歌曲详情(包括封面信息)
接口:热门评论获取
请求地址:https://autumnfish.cn/comment/hot?type=0
请求方法:get
请求参数:id(歌曲编号),type固定为0
响应内容:歌曲的热门评论
*/
playMusic:function(id){
var that = this;
// 获取歌曲地址
axios.get("https://autumnfish.cn/song/url?id="+id)
.then(function(response){
that.musicUrl = response.data.data[0].url;
},function(err){ })
// 获取歌曲封面
axios.get("https://autumnfish.cn/song/detail?ids="+id)
.then(function(response){
that.musicCover = response.data.songs[0].al.picUrl;
},function(err){ })
// 获取歌曲评论
axios.get("https://autumnfish.cn/comment/hot?type=0&id="+id)
.then(function(response){
that.hotComments = response.data.hotComments;
},function(err){ })
}
}
})
</script>
</body>
</html>