vue基础入门

导包

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  • 不推荐新手直接使用 vue-cli,尤其是在你还不熟悉基于 Node.js 的构建工具时,生产环境版本性能高,是开发环境的简要版
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>

第一个Vue程序

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Vue基础</title>
		
	</head>
	<body>
		<div id="app">
		  {{ message }}    <!--{}  叫插值表达式  将数据和页面结构关联-->
		</div>
		<!-- 开发环境版本,包含了有帮助的命令行警告 -->
		<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
		<script type="text/javascript">
			var app = new Vue({
			  el: '#app',   <!--id选择器-->
			  data: {    <!--插值表达式中数据-->
			    message: 'Hello Vue!'
			  }
			})
		</script>
	</body>
</html>

vue实例的作用范围

  • el负责设置挂载的标签元素,el后选择器对应的标签的内部
<body>
		<!--显示为{{message}},而不显示对应的message,不在id为app标签内部-->
		{{message}}
		
		<div id="app">
			<span>{{message}}</span>
		  {{ message }}
		</div>
</body>

其他选择器

  • 会命中多个元素,不建议使用
<script type="text/javascript">
			var app = new Vue({
			  el: '#app',   <!--id选择器-->
			  el: '.app', <!--class选择器-->
			  el: 'div', <!--标签选择器-->
			  data: {    <!--插值表达式中数据-->
			    message: 'Hello Vue!'
			  }
			})
		</script>

选择器支持除html和body之外的双标签

  • id选择器,id写在body或者html标签上时,报错
[Vue warn]: Do not mount Vue to <html> or <body> - mount to normal elements instead

date数据对象

  • json格式:message.属性
  • json数组:message[index]
<body>
	<div id="app">
	  {{ message }}  
	  <br>
	  {{school.name}} {{school.phone}}
	  <br>
	  <ul>
	  	<li>{{campus[0]}}</li>
	  	<li>{{campus[1]}}</li>
	  </ul>
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var app = new Vue({
		  el: '#app',
		  data: {
		    message: '小黑 你好!',
			school:{
				name:"宝贝的家",
				phone:"5201314"
			},
			campus:["宝贝","亲爱的","姐姐","老婆"]
		  }
		})
	</script>
</body>

常见指令

v-text

v-text:设置标签内的内容,默认写法 v-text=“message” 替换全部内容,使用差值表达式 {{message}} 替换指定内容

<body>
	<div id="app">
	  <h2 v-text="message">这里会被替换</h2>    <!--会把h2内部的所有内容替换为message-->
	  <h2>北京{{message}}</h2>    <!--北京拼接message-->
	  <!--内部拼接字符串-->
	  <h2 v-text="message+ '!' "></h2>
	  <h2>北京{{message + "!"}}</h2>
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var vue = new Vue({
			el:"#app",
			data:{
				message:"黑马程序员"
			}
		})
	</script>
</body>

v-html

v-html:设置元素的innerHTML,有html结构会被解析为html标签

<body>
	<div id="app">
		<p v-text="content"></p>
		<p v-html="content"></p>
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var vue = new Vue({
			el:"#app",
			data:{
				content:"<a href='http://www.baidu.com'>百度</a>"
			}
		})
	</script>
</body>

v-on

  • v-on:为元素绑定事件,指令可以写@click,绑定的方法定义在methods:{ 方法名:function(){ 方法 } } ,方法内部通过this关键字可以访问定义在data中的数据,或者本对象的中属性或方法
<body>
	<div id="app">
		<input type="button" value="v-on指令" v-on:click="doSome"/>
		<input type="button" value="v-on简写" @click="doSome"/>
		<p @click="saySome">{{name}}</p>

	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var vue = new Vue({
			el:"#app",
			data:{
				name:"宝贝"
			},
			methods:{
				doSome:function(){
					alert("做点什么?");
				},
				saySome:function(){
					// console.log(this.food)     F12 console界面中查看测试是否成功
					this.name+="爱你";
					// this.doSome();  访问本对象中属性和方法
				}
			}
		})
	</script>
</body>

v-on传参

  • @click=“doSome(参数)”,对应methods方法中定义形参
  • @keyup.enter=“doSome(参数)”,时间后面修饰符对事件限制
<body>
	<div id="app">
		<!--方法传参-->
		<input type="button" value="点我" @click="doSome('宝贝',666)"/>
		<!--  @keyup.enter  enter键弹起触发事件  -->
		<input type="text" @keyup.enter="sayHi('张三')"/>
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var app = new Vue({
			el:"#app",
			methods:{
				doSome:function(p1,p2){
					alert(p1+","+p2)
				},
				sayHi:function(name){
					alert(name + ",吃了吗?")
				}
				
			}
		})
	</script>
</body>

v-model

  • v-model:获取和设置表单元素的值(双向数据绑定),绑定的Vue对象中data和表单元素值关联
  • 更改div标签中的message,或者Vue对象中data中message,都会同步更新对方的值
<body>
	<div id="app">
		<!-- 修改Vue对象中data的值,同步更新到文本框-->
		<input type="button" value="修改name为宝贝" @click="changeName" />
		<br>
		<!-- v-model 双向绑定name  sayHi(name)将当前Vue对象的name作为sayHi方法的参数  -->
		<input type="text" v-model="name" @keyup.enter="sayHi(name)"/>
		<h2>{{name}}</h2>
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var app = new Vue({
			el:"#app",
			data:{
				name:"11"
			},
			methods:{
				sayHi:function(p1){
					<!-- 获取当前Vue对象的name -->
					alert(p1 + ",吃了没?")
					// alert(this.name + ",吃了没?")   也可以不传参数,直接this.name
				},
				changeName:function(){
					this.name = "宝贝"
				}
			}
		})
	</script>
</body>

计数器

<body>
	<div id="app">
		<div class="input-num">
			<button v-on:click="sub">-</button>
			<span>{{num}}</span>
			<button @click="add">+</button>
		</div>
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var app = new Vue({
			el:"#app",
			data:{
				num:1    //设置初始值
			},
			methods:{
				add:function(){
					// console.log('add')    //测试
					if(this.num >= 10){
						alert("最大范围10,已经到顶了!")
					}else{
						this.num++;
					}
				},
				sub:function(){
					// console.log('sub')
					if(this.num <= 0){
						alert("最小范围0,已经到底了!")
					}else{
						this.num--;
					}
				}
			}
		})
	</script>
</body>

v-show

  • v-show:根据isShow标记的真假显示元素的显示状态,原理是修改元素的display,display:none,v-show后面的内容解析为布尔值
<body>
	<div id="app">
		<input type="button" value="切换显示状态" @click="changeIsShow"/>
		<br>
		<img src="jpg/study.png" v-show="true">   <!--v-show="true" 默认显示-->
		<img src="jpg/study.png" v-show="isShow">   <!--使用isShow标记-->
		<br>
		<input type="button" value="长大了!" @click="addAge"/>
		<br>
		<img src="jpg/mm.jpg" v-show="age>=18">   <!--使用布尔表达式-->
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var app = new Vue({
			el:"#app",
			data:{
				isShow:false,    //标记是否显示,与v-show连用
				age:15
			},
			methods:{
				changeIsShow:function(){
					this.isShow = !this.isShow   //状态取反
				},
				addAge:function(){
					this.age++;
				}
			}
		})
	</script>
</body>

v-if

  • v-if:根据表达式真假切换元素的显示状态
  • 本质是直接添加删除dom元素切换显示状态,表达式为true,显示dom元素;表达式为false,移除dom元素
  • 频繁切换的元素用v-show,反之用v-if,操作dom树对性能消耗大
<body>
	<div id="app">
		<input type="button" value="切换显示状态" @click="changeIsShow"/>
		<br>
		<h2 v-if="temprature>=30">热死了!</h2>
		<br>
		<img src="jpg/mm.jpg" v-show="isShow" title="v-show修饰,操作display修饰">
		<img src="jpg/mm.jpg" v-if="isShow" title="v-if修饰,操作dom树,直接删掉添加该标签">
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var app = new Vue({
			el:"#app",
			data:{
				isShow:false,    //标记是否显示,与v-show/v-if连用
				temprature:40
			},
			methods:{
				changeIsShow:function(){
					this.isShow = !this.isShow   //状态取反
				},
			}
		})
	</script>
</body>

v-bind

  • v-bind:为元素绑定属性,src等等
  • v-bind:属性名,简写可以 :属性名
  • 动态增删class使用 :class=“{class类型名:boolean标记}”
<body>
	<div id="app">
		<img v-bind:src="imgSrc">  <!-- v-bind:src 可以简写为 :src -->
		<br>
		<!--使用 v-bind:class 设置元素的class属性,支持表达式-->
		<img :src="imgSrc" :title="imgTitle + '!!!'" :class="isActive?'active':''" @click="toggleActive">
		<!-- :class="{class类型名:boolean标记}"  -->
		<img :src="imgSrc" :title="imgTitle + '!!!'" :class="{active:isActive}" @click="toggleActive">
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var app = new Vue({
			el:"#app",
			data:{
				imgSrc:"https://hao1.qhimg.com/t013767d2f7a43194fb.png",
				imgTitle:"100周年快乐",
				isActive:false
			},
			methods:{
				toggleActive:function(){
					this.isActive = !this.isActive;
				}
			}
		})
	</script>
</body>

图片切换

  • 列表数据:使用数组保存 imgList: [数据,数据]
  • v-bind:设置元素属性
<body>
	<div id="mask">
		<div class="center">
			<h2 class="title"><img src="./images/logo.png" alt=""> mytest</h2>
			<img :src="imgList[index]" />    <!-- imgList[index]  动态获取index-->
			<!-- v-show 使用boolean表达式判断 show还是不show-->
			<a href="javascript:void(0)" @click="prev" class="left" v-show="index>0">
				<img src="./images/prev.png" />
			</a>
			<a href="javascript:void(0)" @click="next" class="right" v-show="index<imgList.length-1">
				<img src="./images/next.png" />
			</a>
		</div>
	</div>

	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	<script>
		const app = new Vue({
			el: "#mask",
			data: {
				imgList: [
					"./images/00.jpg",
					"./images/01.jpg",
					"./images/02.jpg",
				],
				index: 0
			},
			methods: {
				// 上一张
				prev() {   //相当于 pre:function(){}
					this.index--;
				},
				// 下一张
				next() {   //相当于 next:function(){}
					this.index++;
				}
			}
		});
	</script>
</body>

v-for

  • v-for:根据数据(数组,json数组)循环获取
  • v-for="(item,index) in 数据 "
  • item in数据 item和index可以结合其他指令使用
  • 数组长度更新会同步到页面,所谓响应式
<body>
	<div id="app">
		<input type="button" value="添加蔬菜" @click="add"/>
		<input type="button" value="减少蔬菜" @click="remove"/>
		<ul>
			<li v-for="(item,index) in arr">
				昵称{{index+1}} {{item}}
			</li>
		</ul>
		<!-- v-for 可以配合其他指令对每个标签操作-->
		<h2 v-for="item in vegetables" v-bind:title="item.name">{{item.name}}</h2>
	</div>
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
	<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
	<script type="text/javascript">
		var app = new Vue({
			el:"#app",
			data:{
				arr:["宝贝","亲爱的","老婆"],        //数组
				vegetables:[          //json格式数组
					{name:"西红柿炒鸡蛋"},
					{name:"炒白菜"}
				]
			},
			methods:{
				add:function(){
					this.vegetables.push({name:"香菇炒肉"});   //添加到最后一个元素
				},
				remove:function(){
					this.vegetables.shift()();    //移除第一个元素
				}
			}
		})
	</script>
</body>

记事本

  • v-for:根据数组、json数组生成列表结构
  • v-model:表单中内容和对象中数据关联
  • v-on:绑定事件
  • list.splice(index,1) :根据下标删除对应元素,splice(从哪删,删几个)
  • clear:绑定事件,清空数组
<body>
 <!-- 主体区域 -->
 <section id="todoapp">
   <!-- 输入框 -->
   <header class="header">
     <h1>小黑记事本</h1>
     <input v-model="inputValue" @keyup.enter="add" autofocus="autofocus" autocomplete="off" placeholder="请输入任务"
       class="new-todo" />
	<!--placeholder  文本框灰色默认显示-->
   </header>
   <!-- 列表区域 -->
   <section class="main">
     <ul class="todo-list">
       <li class="todo" v-for="(item,index) in list">
         <div class="view">
           <span class="index">{{ index+1 }}.</span>
           <label>{{ item }}</label>
           <button class="destroy" @click="remove(index)"></button>    <!--  都在v-for中,可以使用index和item-->
         </div>
       </li>
     </ul>
   </section>
   <!-- 统计和清空 -->
   <footer class="footer" >
     <span class="todo-count" v-show="list.length!=0">
       <strong>{{list.length}}</strong> items left   <!--差值表达式,同步更新list数组的长度-->
     </span>
     <button class="clear-completed" @click="clear" v-show="list.length!=0">
       Clear
     </button>
   </footer>
 </section>
 <!-- 开发环境版本,包含了有帮助的命令行警告 -->
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <script>
   var app = new Vue({
     el: "#todoapp",
     data: {
       list: ["写代码", "吃饭饭", "睡觉觉"],   //默认显示
       inputValue: "好好学习,天天向上"   //默认显示
     },
     methods: {
       add: function () {
         this.list.push(this.inputValue);   //数组添加元素  list.push(用户输入的数据)
       },
       remove:function(index){
         // console.log("删除");
         // console.log(index);
         this.list.splice(index,1);  //splice(从哪删,删几个)
       },
	clear:function(){
		this.list = [];
	}
     },
   })
 </script>
</body>

网络应用

Vue结合网络数据开发应用

axios

  • axios:网络请求库
  • 导包 ——> 用方法
  • then中回调函数在请求成功或失败时触发
  • 通过回调函数的形参获取响应内容,错误信息
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

axios.get(地址?key1=value&key2=value)
.then(function(resp){
	回调函数;
},function(err){
	错误时,回调函数;
})

axios.post(地址,{key1:value,key2,value})
.then(function(resp){
	回调函数;
},function(err){
	错误时,回调函数;
})

或者

axios.get(地址?key1=value&key2=value)
.then(function(resp){
	回调函数;
}).catch(function(err){     catch表示捕捉异常
	错误时,回调函数;
})

<body>
	<input type="button" value="get请求" class="get"/>  <!--定义类名,js通过类名获取标签-->
	<input type="button" value="post请求" class="post"/>
	<!-- 导入axios包 -->
	<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
	<script>
		/* 
			接口:随机笑话
			请求地址:https://autumnfish.cn/api/joke/list
			请求方法:get
			请求参数:num(笑话条数/数字)
			响应内容:随机笑话
		 */
		document.querySelector(".get").onclick = function(){
			axios.get("https://autumnfish.cn/api/joke/list?num=3")
			.then(function(resp){
				console.log(resp);
			},function(err){
				console.log(err);
			})
		}
		/*
			接口:用户注册
			请求地址:https://autumnfish.cn/api/user/reg
			请求方法:post
			请求参数:username(用户名/字符串)
			响应内容:注册成功或失败
		 */
		document.querySelector(".post").onclick = function(){
			axios.post("https://autumnfish.cn/api/user/reg",{username:"秋刀马丁鱼"})
			.then(function(resp){
				console.log(resp);
			})
		}
	</script>
</body>

axios+vue

  • 注意导包
  • 注意vue methods中函数的this对应的是vue对象,而methods中axios函数中的this对应的是axios对象返回的数据resp
  • 解决办法:把vue对象的this作为一个成员变量,axios获取 resp.data 赋值到成员变量 this 上
<body>
	<div id="app">
		<input type="button" value="获取笑话" @click="getJoke"/>
		<br>
		<p>{{joke}}</p>
	</div>
	
	<!--导入vue包-->
	<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>
		/* 
			接口:随机笑话
			请求地址:https://autumnfish.cn/api/joke
			请求方法:get
			请求参数:无
			响应内容:随机一条笑话
		 */
		var app = new Vue({
			el:"#app",
			data:{
				joke:"一个笑话"
			},
			methods:{
				getJoke:function(){
					// console.log(this.joke);   当前的this是Vue对象
					var that = this;       //定义一个成员变量指向Vue对象
					axios.get("https://autumnfish.cn/api/joke")
					.then(function(resp){
						// console.log(this.joke);   当前的this是axios返回对象resp对象
						// console.log(resp);      测试返回的数据
						that.joke = resp.data;     //此时的joke是成员变量指向的Vue对象的joke
					},function(err){
						that.joke = "没有获取到笑话";
					})
				}
			}
		})
	</script>
</body>

查询天气

  • 具体的业务,js通常封装到独立的js文件中
  • axios中的this指向axios对象:要在axios所在方法,定义成员变量 var that = this,实现在axios中的this(that) 指向Vue对象
  • 单纯函数中的this指向的是Vue对象
/*
main.js
  请求地址:http://wthrcdn.etouch.cn/weather_mini
  请求方法:get
  请求参数:city(城市名)
  响应内容:天气信息

  1. 点击回车
  2. 查询数据
  3. 渲染数据
  */
 
 var app = new Vue({
	 el:"#app",
	 data:{
		 city:'',
		 weatherList:[]
	 },
	 methods:{
		 searchWeather:function(){
			 // console.log("天气查询");   //测试方法
			 console.log(this.city);  //测试能否拿到双向绑定输入的city
			 var that = this;  //定义成员变量
			 //  调用接口
			 axios.get("http://wthrcdn.etouch.cn/weather_mini?city="+this.city)
			 .then(function(resp){
				 // console.log(resp)  //测试api返回数据
				 // console.log(resp.data.data.forecast)
				 that.weatherList = resp.data.data.forecast;
			 }).catch(function(err){
				 alert("查询出错")
			 })
		 },
		 
		 //axios中的this指向axios对象:要在axios所在方法,定义成员变量 var that = this,实现在axios中的this(that) 指向Vue对象
		 //单纯函数中的this指向的是Vue对象
		 changeCity:function(city){
			 this.city = city;
			 this.searchWeather();
		 }
	 }
 })
<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">
		  <!--  双向绑定city,拿到输入的内容  -->
        <input type="text" class="input_txt" v-model="city" @keyup.enter="searchWeather()" placeholder="请输入查询的天气"/>
        <button class="input_sub" @click="searchWeather()" >
          搜 索
        </button>
      </div>
      <div class="hotkey">
        <a href="javascript:;" @click="changeCity('北京')">北京</a>
        <a href="javascript:;" @click="changeCity('上海')">上海</a>
        <a href="javascript:;" @click="changeCity('深圳')">深圳</a>
        <a href="javascript:;" @click="changeCity('南京')">南京</a>
      </div>
    </div>
    <ul class="weather_list">
      <li v-for="item in weatherList">    <!--  循环获取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="./js/main.js"></script>
</body>

音乐播放器

  • 服务器api接口返回的数据比较复杂,注意层级结构
  • 响应式数据都定义在data中
  • axios获取整个接口返回对象,确定的标签中获取整个返回对象中的确定内容,{{item.name}}
<!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>Document</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' ref='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 @click="playMv(item.mvid)" v-if="item.mvid!=0"></i>    <!-- v-if 切换span的显示状态-->
              </span>
            </li>
          </ul>
          <img src="images/line.png" class="switch_btn" alt="">
        </div>
        <!-- 歌曲信息容器 -->
        <div class="player_con" :class="{playing:isPlay}">  <!-- v-bind:class 布尔表达式切换class类型是否存在 -->
          <img src="images/player_bar.png" class="play_bar" />
          <!-- 黑胶碟片 -->
          <img src="images/disc.png" class="disc autoRotate" />   
          <img :src="coverUrl==''?'./images/cover.png':coverUrl" class="cover autoRotate" />  <!-- v-bind:src 动态改变src -->
        </div>
        <!-- 评论容器 -->
        <div class="comment_wrapper" ref='comment_wrapper'>
          <h5 class='title'>热门留言</h5>
          <div class='comment_list'>

            <dl v-for="item in hotComments">
              <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" v-show="showVideo">
        <video ref='video' :src="mvUrl" controls="controls"></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 type="text/javascript">
    // 设置axios的基地址
    axios.defaults.baseURL = 'https://autumnfish.cn';
    // axios.defaults.baseURL = 'http://localhost:3000';



    // 实例化vue
    var app = new Vue({
      el: "#player",
      // 需要响应的的数据都放在data中
      data: {
        // 搜索关键字
        query: '',
        // 歌曲列表
        musicList: [],
        // 歌曲url
        musicUrl: '',
        // 是否正在播放
        isPlay: false,
        // 歌曲热门评论
        hotComments: [],
        // 歌曲封面地址
        coverUrl: '',
        // 显示视频播放
        showVideo: false,
        // mv地址
        mvUrl: ''
      },
      // 方法
      methods: {
        // 搜索歌曲
        searchMusic() {
          if (this.query == 0) {
            return
          }
          axios.get('/search?keywords=' + this.query).then(response => {
            // 保存内容
            this.musicList = response.data.result.songs;

          })

          // 清空搜索
          this.query = ''
        },
        // 播放歌曲
        playMusic(musicId) {
          // 获取歌曲url
          axios.get('/song/url?id=' + musicId).then(response => {
            // 保存歌曲url地址
            this.musicUrl = response.data.data[0].url
          })
          // 获取歌曲热门评论
          axios.get('/comment/hot?type=0&id=' + musicId).then(response => {
            // console.log(response)
            // 保存热门评论
            this.hotComments = response.data.hotComments

          })
          // 获取歌曲封面
          axios.get('/song/detail?ids=' + musicId).then(response => {
            // console.log(response)
            // 设置封面
            this.coverUrl = response.data.songs[0].al.picUrl
          })

        },
        // audio的play事件
        play() {
          this.isPlay = true
          // 清空mv的信息
          this.mvUrl = ''
        },
        // audio的pause事件
        pause() {
          this.isPlay = false
        },
        // 播放mv
        playMv(vid) {
          if (vid) {
            this.showVideo = true;
            // 获取mv信息
            axios.get('/mv/url?id=' + vid).then(response => {
              // console.log(response)
              // 暂停歌曲播放
              this.$refs.audio.pause()
              // 获取mv地址
              this.mvUrl = response.data.data.url
            })
          }
        },
        // 关闭mv界面
        closeMv() {
          this.showVideo = false
          this.$refs.video.pause()
        },
        // 搜索历史记录中的歌曲
        historySearch(history) {
          this.query = history
          this.searchMusic()
          this.showHistory = false;
        }
      },

    })

  </script>
</body>

</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值