1. Vue基础
1.1 Vue简介
- JavaScript框架
- 简化Dom操作
- 响应式的数据操作
1.2 第一个Vue程序
1.2.1 导入开发环境
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
或者(新手推荐使用)
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
1.2.2 编写页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">{
{message}}</div>
<script> var vue = new Vue({
el:"#app", data:{
message:"i love java !" } }) </script>
</body>
</html>
1.2.3 运行结果
1.3 el挂载点
提出问题:
- vue实例的作用范围是什么呢?
{
{ message }}
<div class="text">{
{ message }},{
{ info }}}</div>
<script> var el2 = new Vue({
el:".text", data:{
message:"测试class选择器~", info: "内部信息" } }); </script>
测试结果:
2. 是否可以使用其它选择器
答:el挂载点命中的有id选择器(#),class选择器(.)和标签选择器(标签名)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>el</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div>{
{ message }}</div>
<div class="text">{
{ message }}</div>
<div id="app">{
{ message }}</div>
<script> var el1 = new Vue({
el:"div", data:{
message:"测试标签选择器~" } }); var el2 = new Vue({
el:".text", data:{
message:"测试class选择器~" } }); var el3 = new Vue({
el: "#app", data:{
message:"测试id选择器~" } }); </script>
</body>
</html>
- 是否可以设置其它的dom元素呢?
可以使用常用的标签库,如p标签,h1标签,但推荐使用div标签。
注意:
1.4 data数据对象
data域可以存储基本数据类型,还可以存储其它数据类型:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>data</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{
{name}}</h2>
<ul>
<li>{
{info.age}}}</li>
<li>{
{info.tel}}</li>
</ul>
<h2>{
{lan[0]}}</h2>
<h2>{
{lan[1]}}</h2>
<h2>{
{lan[2]}}</h2>
</div>
<script> var data = new Vue({
el:"#app", data:{
name: "liuzeyu", info:{
age: 14, tel:10086 }, lan:["C++","C","Java"] } }); </script>
</body>
</html>
运行结果:
2. 本地应用
2.1 v-text指令
v-text是一个标签体的属性,可以用于直接替换标签体内容,如果只需要进行部分替换,可以直接使用{ {}}
<div id="app">
<h2 v-text="message+'@'"></h2>
<h2>{
{message}},北京@</h2>
</div>
<script> var v = new Vue({
el: "#app", data: {
message:"测试v-text!!!" } }); </script>
运行结果:
2.2 v-htmlt 指令
v-html指令会将带有html标签的字符串转成html
<div id="app">
<h2 v-html="href">百度</h2>
<h2 v-text="href">百度</h2>
</div>
<script> var html = new Vue({
el:"#app", data:{
href:"<a href='http://www.baidu.com'>百度</a>" } }); </script>
运行结果:
2.3 v-on 指令
v-on指令绑定事件函数,常见的投点击事件,双击事件,鼠标事件
<body>
<div id="app">
<input type="button" value="v-on指令" v-on:click="doIt" >
<input type="button" value="v-on简写" @click="doIt">
<input type="button" value="v-on双击" @dblclick="doIt">
<h3 @click="doFood" v-text="food"></h3>
</div>
<script> var on = new Vue({
el:"#app", data:{
food:"西红柿炒蛋..." }, methods:{
doIt:function () {
alert("haha"); }, doFood:function () {
this.food +="好吃好吃" } } }); </script>
</body>
其中使用this关键字,点击h3会给内容追加字符串,可以不用操作dom元素。
补充:传递自定义参数修饰符
<input type="button" value="传参" @click="doStudy">
doStudy:function (msg) {
alert(msg);
}
2.4 计数器
<body>
<div id="app">
<button @click="sub">-</button>
<span v-text="num">{
{num}}</span>
<button @click="add">+</button>
</div>
<script> var counter = new Vue({
el:"#app", data:{
num: 0 }, methods:{
sub:function () {
this.num --; if( this.num < 0 ){
alert("求求你不要再减了..."); } }, add:function () {
this.num ++; if(this.num > 10){
alert("求求你不要再加了..."); } } } }); </script>
</body>
2.5 v-show指令
- v-show指令的作用:根据表达式的真假切换元素的显示状态
- 本质是通过操纵<mark>dom标签的属性display</mark>来切换显示状态
- 表达式的值为true,显示标签的display属性为none
<body>
<div id="app">
<img src="public/favicon.ico" v-show="isShow">
<input type="button" value="切换" @click="change">
</div>
<script> var show = new Vue({
el:"#app", data:{
isShow:false }, methods:{
change:function () {
this.isShow = !this.isShow; } } }); </script>
</body>
2.6 v-if指令
- v-if指令的作用:根据表达式的真假切换元素的显示状态
- 本质是通过操纵dom元素来切换显示状态
- 表达式的值为true,存在存在于dom树中,表达式值为false,从dom树中移除
<body>
<div id="app">
<p v-if="isShow">刘泽煜</p>
<input type="button" value="切换" @click="change">
</div>
<script> var v_if = new Vue({
el:"#app", data:{
isShow:true }, methods:{
change:function () {
this.isShow = !this.isShow; } } }); </script>
</body>
运行结果:
<mark>对比 v-if 和 v-show:</mark>
两者都是显示和隐藏标签内容,但是v-if操作的是dom树的标签,需要删除和添加标签节点,如果是经常需要改变的标签不适合适应,会影响到效率。
v-show则是为标签添加属性和删除属性,适用于经常操作的标签。
2.7 v-bind指令
v-bind为<mark>标签的属性值</mark>添加值,可以增加和修改
<body>
<div id="app">
<img v-bind:src="imgSrc" width="10%" height="10%">
<br>
<img :src="imgSrc" alt="" width="10%" height="10%">
<hr>
<img :src="imgSrc" alt="" width="10%" height="10%" :class="isActive?'active':''">
<img :src="imgSrc" alt="" width="10%" height="10%" :class="{active:isActive}">
<input type="button" @click="addStyle" value="为照片添加样式">
<br>
</div>
<script> var img = new Vue({
el:"#app", data:{
imgSrc:"http://pngimg.com/uploads/sky_lantern/sky_lantern_PNG65.png", isActive:false }, methods:{
addStyle:function () {
this.isActive = !this.isActive; } } }); </script>
</body>
运行结果:
2.8 v-for指令
- v-for指令的作用是根据数据生成的列表结构
- 数组常与v-for结合使用
- 语法是(item,index) in 数据
- 数组长度的更新会同步到页面上,是响应式的
<body>
<div id="app">
<ul>
<li v-for="addr in address">{
{addr}}</li>
</ul>
<hr>
<ul>
<li v-for="(item,index) in address">{
{index+1}},{
{item}}</li>
</ul>
</div>
<script> var v_for = new Vue({
el:"#app", data:{
address:["北京","上海","广州","深圳"] person:{
name:"liuzeyu", age:18 } } }); </script>
</body>
运行结果:
2.9 v-model
v-model的作用是可以将表单得到的值和data中的值进行绑定,并且数据同步是双向的,所谓的双向:指的是我们在input中输入的信息,会被赋值给Vue中的data message变量,之后,message变量又会重新赋值给span标签内容。
<body>
<div id="app">
<input type="text" v-model="message">
<span>{
{ message }}</span>
</div>
<script> var model = new Vue({
el:"#app", data:{
message:"卧槽!" } }); </script>
</body>
运行结果:
2.10 小黑记事本
需求:
实现对记事本的增加,删除,统计条数,清空功能。
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>小黑记事本</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="robots" content="noindex, nofollow" />
<meta name="googlebot" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" type="text/css" href="./css/index.css" />
</head>
<body>
<!-- 主体区域 -->
<section id="todoapp">
<!-- 输入框 -->
<header class="header">
<h1>小黑记事本</h1>
<input autofocus="autofocus" autocomplete="off" placeholder="请输入任务" class="new-todo" v-model="inputValue" @keyup.enter="addTodo" />
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="todo-list">
<li class="todo" v-for="(item,index) in hobbies">
<div class="view" >
<span class="index" >{
{index}}.</span>
<label>{
{item}}</label>
<button class="destroy" @click="remove(index)"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer" v-if="hobbies.length != 0">
<span class="todo-count"> <strong>{
{hobbies.length}}</strong> items left </span>
<button class="clear-completed" @click="clear">
Clear
</button>
</footer>
</section>
<!-- 底部 -->
<footer class="info">
<p>
<a href="http://www.itheima.com/" ><img src="./img/black.png" alt="" /></a>
</p>
</footer>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script> var v = new Vue({
el:"#todoapp", data:{
hobbies:["唱歌","吃饭","跳舞"], inputValue:"" }, methods:{
addTodo:function () {
this.hobbies.push(this.inputValue); }, remove:function (index) {
this.hobbies.splice(index,1); //点击一次删除一个 }, clear:function () {
this.hobbies =[]; //将数组置为空 } } },); </script>
</body>
</html>
使用到的指令:
1. v-for:遍历集合
2. v-model:数据的双向绑定
3. @click = “”:点击函数
使用到的函数:
1. [].length:求数组的长度
2. [].splice(index,count):删除索引对应的数据
3. [].push:为数组添加元素
3. 网络应用
3.1 axios的基本使用
axios的两种请求方式:
- get:格式:axios.get(“调用的接口地址?参数1=值1&参数2=值2”).then(回调函数1,回调函数2);
- post:axios.post(“接口调用地址”,{参数1:“值1”,参数2:“值2”}).then(回调函数1,回调函数2);
<!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>axios基本使用</title>
</head>
<body>
<input type="button" value="get请求" class="get">
<input type="button" value="post请求" class="post">
<!-- 官网提供的 axios 在线地址 -->
<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=1").then(function (response) {
console.log(response.data.jokes); },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:"liuzeyu"}).then( function (response) {
console.log(response.data); },function (err) {
console.log(err); } ); } </script>
</body>
</html>
3.2 使用axios+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>axios+vue</title>
</head>
<body>
<div id="app">
<input type="button" value="获取笑话" @click="getJoke">
<p> {
{ joke }}</p>
</div>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script> /* 接口:随机获取一条笑话 请求地址:https://autumnfish.cn/api/joke 请求方法:get 请求参数:无 响应内容:随机笑话 */ var v = new Vue({
el:"#app", data:{
joke: }, methods:{
getJoke:function () {
var that = this; axios.get("https://autumnfish.cn/api/joke").then( function (response) {
that.joke = response.data; }, function (err) {
this.joke = err; } ); } } }); </script>
</body>
</html>
3.3 天知道
<!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>
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/index.css" />
</head>
<body>
<div class="wrap" id="app">
<div class="search_form">
<div class="logo"><img src="img/logo.png" alt="logo" /></div>
<div class="form_group">
<input type="text" class="input_txt" placeholder="请输入查询的天气" v-model="city" @keyup.enter="search" />
<button class="input_sub" @click="search">
搜 索
</button>
</div>
<div class="hotkey">
<a href="javascript:;" @click="hotadd('北京')">北京</a>
<a href="javascript:;" @click="hotadd('上海')">上海</a>
<a href="javascript:;" @click="hotadd('广州')">广州</a>
<a href="javascript:;" @click="hotadd('深圳')">深圳</a>
</div>
</div>
<ul class="weather_list" >
<li v-for="(item,index) in weatherList">
<div class="info_type"><span class="iconfont">{
{item.type}}</span></div>
<div class="info_temp">
<b>{
{item.low}}</b>
~
<b>{
{item.high}}</b>
</div>
<div class="info_date"><span>{
{item.date}}</span></div>
</li>
</ul>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 自己的js -->
<script src="main.js"></script>
</body>
</html>
js文件
var v = new Vue({
el:"#app",
data:{
city:"",
weatherList:""
},
methods:{
search:function () {
// console.log(this.city);
var that = this;
axios.get("http://wthrcdn.etouch.cn/weather_mini?city="+this.city).then(function (response) {
// console.log(response.data.data.forecast);
that.weatherList = response.data.data.forecast;
},function (err) {
});
},
hotadd:function (city) {
this.city = city;
this.search();
}
}
});
运行结果:
4. 综合应用
实现一个在线的音乐播放器:
模块开发:
- 歌曲搜索
- 歌曲播放
- 歌曲封面
- 歌曲评论
- 播放动画
- mv播放
涉及到的接口开发文档:
1:歌曲搜索接口
请求地址:https://autumnfish.cn/search
请求方法:get
请求参数:keywords(查询关键字)
响应内容:歌曲搜索结果
2:歌曲url获取接口
请求地址:https://autumnfish.cn/song/url
请求方法:get
请求参数:id(歌曲id)
响应内容:歌曲url地址
3.歌曲详情获取
请求地址:https://autumnfish.cn/song/detail
请求方法:get
请求参数:ids(歌曲id)
响应内容:歌曲详情(包括封面信息)
4.热门评论获取
请求地址:https://autumnfish.cn/comment/hot?type=0
请求方法:get
请求参数:id(歌曲id,地址中的type固定为0)
响应内容:歌曲的热门评论
5.mv地址获取
请求地址:https://autumnfish.cn/mv/url
请求方法:get
请求参数:id(mvid,为0表示没有mv)
响应内容:mv的地址
静态页面:
<!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>悦听player</title>
<!-- 样式 -->
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div class="wrap">
<!-- 播放器主体区域 -->
<div class="play_wrap" id="player">
<div class="search_bar">
<img src="images/player_title.png" alt="" />
<!-- 搜索歌曲 -->
<input type="text" autocomplete="off" v-model="query" @keyup.enter="searchMusic" />
</div>
<div class="center_con">
<!-- 搜索歌曲列表 -->
<div class='song_wrapper'>
<ul class="song_list">
<li v-for="item in musicList">
<a href="javascript:;" @click="playMusic(item.id)"></a>
<b>{
{item.name}}</b>
<span><i v-show="item.mvid != 0" @click="playMv(item.mvid)"></i></span>
</li>
</ul>
<img src="images/line.png" class="switch_btn" alt="">
</div>
<!-- 歌曲信息容器 -->
<div class="player_con" :class="{playing :isPlaying}">
<img src="images/player_bar.png" class="play_bar" />
<!-- 黑胶碟片 -->
<img src="images/disc.png" class="disc autoRotate" />
<img :src="musicCover" class="cover autoRotate" />
</div>
<!-- 评论容器 -->
<div class="comment_wrapper">
<h5 class='title'>热门留言</h5>
<div class='comment_list'>
<dl v-for="item in musicComments">
<dt><img :src="item.user.avatarUrl" alt=""></dt>
<dd class="name">{
{item.user.nickname}}</dd>
<dd class="detail">
{
{item.content}}
</dd>
</dl>
</div>
<img src="images/line.png" class="right_line">
</div>
</div>
<div class="audio_con">
<audio ref='audio' @play="play" @pause="pause" :src="musicUrl" controls autoplay loop class="myaudio"></audio>
</div>
<div class="video_con" style="display: none;" v-show="isShow">
<video controls="controls" :src="mvUrl"></video>
<div class="mask" @click="closeMv"></div>
</div>
</div>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="main.js"></script>
</body>
</html>
js文件:
var v = new Vue({
el:"#player",
data:{
query:"",
musicList:[],
musicUrl:"",
musicCover:"",
musicComments:[],
isPlaying:false,
isShow:false,
mvUrl:""
},
methods:{
//搜索音乐
searchMusic:function () {
var that = this;
axios.get("https://autumnfish.cn/search?keywords="+this.query).then(function (response) {
that.musicList = response.data.result.songs;
console.log(response);
},function (err) {
//console.log(err);
});
},
//点击播放音乐
playMusic:function (musicId) {
var that = this;
axios.get("https://autumnfish.cn/song/url?id="+musicId).then(function (response) {
that.musicUrl = response.data.data[0].url;
},function (err) {
console.log(err);
});
axios.get("https://autumnfish.cn/song/detail?ids="+musicId).then(
function (response) {
that.musicCover = response.data.songs[0].al.picUrl;
},function (err) {
}
);
axios.get("https://autumnfish.cn/comment/hot?type=0&id="+musicId).then(function (response) {
that.musicComments = response.data.hotComments;
},function (err) {
});
},
pause:function () {
this.isPlaying = false;
},
play:function () {
this.isPlaying = true;
},
//播放MV
playMv:function (mvid) {
var that = this;
axios.get("https://autumnfish.cn/mv/url?id="+mvid).then(function (response) {
that.isShow = true;
that.mvUrl = response.data.data.url;
},function (err) {
});
},
//关闭MV
closeMv:function () {
this.isShow = false;
}
}
});
参考:黑马视频学习