1.Vue
1.1.什么是Vue
1.2.如何使用Vue
官网下载Vue.js (vuejs.org)https://cn.vuejs.org/index.html
<%-- Created by IntelliJ IDEA. User: ykq Date: 2022/5/23 Time: 14:16 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> <%--导入vue得脚本--%> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <%--创建一个双标签--%> <div id="app"> <%--使用vue这种定义得数据 这是vue得语法--%> {{name}}<br> {{age}} </div> </body> <script> /*创建一个Vue对象*/ var app = new Vue({ //把该对象挂载到div标签上 el属性是必有 el: "#app", //data:数据区 定义一些数据 这些数据得类型可以是任意类型。 data: { name:"闫克起", age: 15, hobby:["游泳","看书","玩游戏"], } }) </script> </html>
总结: (1)导入vue.js文件 (2)创建一个双标签: (3) 创建一个vue对象并使用el挂载到双标签上。
1.3.el挂载点
Vue实例的作用范围是什么呢?
Vue会管理el选项命中的元素及其内部的后代元素
是否可以使用其他的选择器?
可以,一般我们使用id,因为id是唯一得。
是否可以设置其他的dom元素呢?
可以,必须该dom是一个双标签。不能是body html标签
1.4.data属性
定义vue得数据。 可以定义为任意类型得数据。
1.5.本地应用
Vue指定: 以v-开始,并且可以在标签内容使用得。vue可以解析这个指令。
1.5..1.v-text和v-html
设置标签的文本值(textContent)
v-text:不能解析html标签
v-html: 可以解析html标签。
<%--
Created by IntelliJ IDEA.
User: ykq
Date: 2022/5/23
Time: 14:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<%--导入vue得脚本--%>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<%--创建一个双标签--%>
<div id="app">
<%--使用{{}}显示标签内容--%>
<span>{{name}}你好</span><br>
<%--设置span得内容 会把span中得原来得内容覆盖--%>
<span v-text="name">你好</span>
</div>
</body>
<script>
/*创建一个Vue对象*/
var app = new Vue({
//挂载vue对象到指定得标签上,该vue对象就可以作用在该标签以及子标签内有效
el:"#app",
data:{
name:"刘德华",
age:18,
hobby:["你好","大家好"]
}
})
</script>
</html>
1.5.2.v-on指令
为元素绑定事件
回顾:
在元素上使用οnclick="方法名"。或 $("#元素").click(function(){})
<%--
Created by IntelliJ IDEA.
User: ykq
Date: 2022/5/23
Time: 14:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<%--导入vue得脚本--%>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<%--创建一个双标签--%>
<div class="app">
{{age}}<br>
<%--绑定点击事件--触发add方法。在vue中定义方法。如果方法是无参可以省略()--%>
<input type="button" value="点击" v-on:click="add"/><br>
<%--vue提供了一种简洁模式@等价于v-on:--%>
<input type="button" value="点击2" @click="sub"/><br>
</div>
</body>
<script>
/*创建一个Vue对象*/
var app = new Vue({
//挂载vue对象到指定得标签上,该vue对象就可以作用在该标签以及子标签内有效
el:".app",
data:{
name:"刘德华",
age:18,
hobby:["你好","大家好"]
},
//表示vue中定义得方法。
methods:{
//无需添加function关键字
add(){
//使用上面得data数据. this当前类对象 Vue对象
this.age++;
},
sub(){
this.age--;
}
}
})
</script>
</html>
1.5.3 v-show和v-if
根据表达值的真假,切换元素的显示和隐藏
<%--
Created by IntelliJ IDEA.
User: ykq
Date: 2022/5/23
Time: 14:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<%--导入vue得脚本--%>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<%--创建一个双标签--%>
<div class="app">
{{age}}<br>
<%--v-show:判断表达式是否为真如果为真则显示指令所在得标签。通过css得display来控制标识得显示和隐藏--%>
<img src="imgs/1.jpg" width="100" height="200" v-show="age>18&&age<25"/>
<%--v-if:根据表达式得真假控制标签得显示。通过创建和移除标签来控制显示和隐藏。如果显示和隐藏得频率非常高,那么该标签得效率会低--%>
<img src="imgs/1.jpg" width="100" height="200" v-if="age>18&&age<25"/>
<br>
<input type="button" value="点检" @click="fun"/>
</div>
</body>
<script>
/*创建一个Vue对象*/
var app = new Vue({
//挂载vue对象到指定得标签上,该vue对象就可以作用在该标签以及子标签内有效
el:".app",
data:{
flag:true,
age:17,
},
methods:{
fun(){
this.age++;
}
}
})
</script>
</html>
1.5.4 v-bind
设置元素的属性 绑定元素得属性值。
<%--
Created by IntelliJ IDEA.
User: ykq
Date: 2022/5/23
Time: 14:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<%--导入vue得脚本--%>
<script type="text/javascript" src="js/vue.js"></script>
<style>
.myimg {
border: 2px solid red;
}
</style>
</head>
<body>
<%--创建一个双标签--%>
<div class="app">
<%--v-bind:设置标签得属性--%>
<img v-bind:src="imgSrc" width="100px" height="100px" v-bind:class="flag?'myimg':''"/>
<%--vue提供了一种简洁模式: 省略v-bind --%>
<img :src="imgSrc" width="100px" height="100px" :class="flag?'myimg':''"/><br>
<input type="button" value="点击" @click="fun"/>
</div>
</body>
<script>
/*创建一个Vue对象*/
var app = new Vue({
//挂载vue对象到指定得标签上,该vue对象就可以作用在该标签以及子标签内有效
el: ".app",
data: {
imgSrc: "imgs/1.jpg",
flag: true
},
methods: {
fun() {
this.imgSrc = "imgs/dl.jpg";
this.flag = !this.flag
}
}
})
</script>
</html>
计数器:使用v-on
<%--
Created by IntelliJ IDEA.
User: w
Date: 2022/5/23
Time: 20:00
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>计数器</title>
<!--引入vue脚本-->
<script type="text/javascript" src="js/vue.js"></script>
<style>
#app{
width:480px;
height:80px;
margin:0px auto;
}
.input{
margin-top:20px;
height:100%;
display:flex;
border-radius:10px;
overflow:hidden;
box-shadow:4px 4px 4px #adadad;
border:1px solid #c7c7c7;
background-color: #c7c7c7;
}
.input input[type='button']{
width:150px;
height:100%;
font-size:40px;
color:#ad2a27;
cursor:pointer;
border:none;
outline:none;
background-color:rgba(0,0,0,0);
}
.input span{
height: 100%;
font-size: 40px;
flex: 1;
text-align: center;
line-height: 80px;
font-family:auto;
background-color: white;
}
</style>
</head>
<body>
<!--html结构-->
<div id="app">
<!--计数器功能区域-->
<div class="input">
<input type="button" value="-" @click="dec">
<span v-html="number"></span>
<input type="button" value="+" @click="add">
</div>
</div>
</body>
<script>
<!--创建vue对象-->
var app = new Vue({
el:"#app",
data:{
number:0,
},
methods:{
add(){
this.number++;
},
dec(){
this.number--;
}
}
});
</script>
</html>
图片切换:使用v-bind v-on
<%--
Created by IntelliJ IDEA.
User: w
Date: 2022/5/23
Time: 20:32
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>图片切换</title>
<script type="text/javascript" src="js/vue.js"></script>
<!--<link href="css/css/index.css" rel="stylesheet">-->
<style>
* {
margin: 0;
padding: 0;
}
html,
body,
#mask {
width: 100%;
height: 100%;
}
#mask {
background-color: #c9c9c9;
position: relative;
}
#mask .center {
position: absolute;
background-color: #fff;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 10px;
}
#mask .center .title {
position: absolute;
display: flex;
align-items: center;
height: 56px;
top: -61px;
left: 0;
padding: 5px;
padding-left: 10px;
padding-bottom: 0;
color: rgba(175, 47, 47, 0.8);
font-size: 26px;
font-weight: normal;
background-color: white;
padding-right: 50px;
z-index: 2;
}
#mask .center .title img {
height: 40px;
margin-right: 10px;
}
#mask .center .title::before {
content: "";
position: absolute;
width: 0;
height: 0;
border: 65px solid;
border-color: transparent transparent white;
top: -65px;
right: -65px;
z-index: 1;
}
#mask .center > img {
display: block;
width: 700px;
height: 458px;
}
#mask .center a {
text-decoration: none;
width: 45px;
height: 100px;
position: absolute;
top: 179px;
vertical-align: middle;
opacity: 0.5;
}
#mask .center a :hover {
opacity: 0.8;
}
#mask .center .left {
left: 15px;
text-align: left;
padding-right: 10px;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
}
#mask .center .right {
right: 15px;
text-align: right;
padding-left: 10px;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
}
</style>
</head>
<body>
<div id="mask">
<div class="center">
<h2 class="title">
<img src="imgs/logo.png">
深圳创维校区环境
</h2>
<!--图片-->
<img :src="imgs[index]">
<!--左箭头-->
<a href="javascript:void(0)" class="left" @click="pre" v-show="index!=0">
<img src="imgs/prev.png">
</a>
<!--右箭头-->
<a href="javascript:void(0)" class="right" @click="next" v-show="index<imgs.length-1">
<img src="imgs/next.png">
</a>
</div>
</div>
</body>
<script>
var app = new Vue({
el:"#mask",
data:{
//定义所有图片的地址
imgs:["imgs/00.jpg","imgs/01.jpg","imgs/02.jpg","imgs/03.jpg","imgs/04.jpg","imgs/05.jpg","imgs/06.jpg","imgs/07.jpg","imgs/08.jpg","imgs/09.jpg","imgs/10.jpg"],
//图片的下标
index:0
},
methods:{
pre(){
this.index--;
},
next(){
this.index++;
}
}
});
</script>
</html>
1.5.5.v-for
循环遍历指令
v-for="(变量名,下标) in 数组|集合"
<%--
Created by IntelliJ IDEA.
User: ykq
Date: 2022/5/23
Time: 14:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<%--导入vue得脚本--%>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<%--创建一个双标签--%>
<div class="app">
<ul>
<li v-for="(a,index) in hobby">{{index}}---->{{a}}</li>
</ul>
<table border="1" width="200" cellpadding="0" cellspacing="0">
<tr v-for="(item,index) in peoples">
<td>{{index}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>{{item.address}}</td>
</tr>
</table>
</div>
</body>
<script>
/*创建一个Vue对象*/
var app = new Vue({
//挂载vue对象到指定得标签上,该vue对象就可以作用在该标签以及子标签内有效
el:".app",
data:{
hobby:["游泳","爬山","看书"],
peoples:[
{"name":"张三1","age":15,"address":"郑州1"},
{"name":"张三2","age":15,"address":"郑州2"},
{"name":"张三3","age":15,"address":"郑州3"}
]
}
})
</script>
</html>
1.5.6.v-on补充
传递自定义参数,事件修饰符
<%--
Created by IntelliJ IDEA.
User: ykq
Date: 2022/5/23
Time: 14:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<%--导入vue得脚本--%>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<%--创建一个双标签--%>
<div class="app">
<table border="1" width="200" cellpadding="0" cellspacing="0">
<tr v-for="(item,index) in peoples" >
<td>{{index}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>{{item.address}}</td>
<td>
<a @click="del(item)">删除</a>
</td>
</tr>
</table>
<%--keyup:键盘弹起事件 enter:回车键--%>
<input type="text" name="name" @keyup.enter="show('hello')"/>
</div>
</body>
<script>
/*创建一个Vue对象*/
var app = new Vue({
//挂载vue对象到指定得标签上,该vue对象就可以作用在该标签以及子标签内有效
el:".app",
methods:{
del(n){
console.log(n);//浏览器控制台输出
},
show(c){
alert("触发了回车键"+c);
}
},
data:{
peoples:[
{"name":"张三1","age":15,"address":"郑州1"},
{"name":"张三2","age":15,"address":"郑州2"},
{"name":"张三3","age":15,"address":"郑州3"}
]
}
})
</script>
</html>
1.5.7.v-model
获取和设置表单元素的值
哪些是表单元素?
<input type="text|password|hidden|radio|checkbox"/>
<select>
<textarea>
<%--
Created by IntelliJ IDEA.
User: ykq
Date: 2022/5/23
Time: 14:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<%--导入vue得脚本--%>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<%--创建一个双标签
v-model它属于双向绑定:如果输入框发送改变,属性name也会跟着变。
如果name属性改变,则输入得内容也会改变。
--%>
<div class="app">
{{name}}<br>
<input type="text" v-model="name"/><button @click="fun">点击</button>
</div>
</body>
<script>
/*创建一个Vue对象*/
var app = new Vue({
//挂载vue对象到指定得标签上,该vue对象就可以作用在该标签以及子标签内有效
el:".app",
data:{
name:"张三",
},
methods:{
fun(){
this.name="刘德华"
}
}
})
</script>
</html>
1.5.8.练习
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>小黑记事本</title>
<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/Bookindex.css" />
</head>
<body>
<!-- 主体区域 -->
<section id="todoapp">
<!-- 输入框 -->
<header class="header">
<h1>小黑记事本</h1>
<input
autofocus="autofocus"
autocomplete="off"
placeholder="请输入任务"
class="new-todo"
v-model="content"
@keyup.enter="add"
/>
</header>
<!-- 列表区域 -->
<section class="main">
<ul class="todo-list">
<li class="todo" v-for="(item,index) in hobby">
<div class="view">
<span class="index">{{index+1}}.</span> <label>{{item}}</label>
<button class="destroy" @click="remove(index)"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer">
<span class="todo-count"> <strong>1</strong> items left </span>
<button class="clear-completed">
Clear
</button>
</footer>
</section>
<!-- 底部 -->
<footer class="info">
<p>
<a href="http://www.baidu.com"
><img src="./img/logo.png" alt=""
/></a>
</p>
</footer>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="../js/vue.js"></script>
<script>
var app=new Vue({
el:"#todoapp",
data:{
//列表内容
hobby:["吃饭","睡觉","打豆豆"],
//输入框内容
content:"",
},
methods:{
add(){
//往数组中添加输入得值
this.hobby.push(this.content);
},
remove(index){
//移除数组中指定下标得元素 从哪开始移除 移除得个数
this.hobby.splice(index,1);
}
}
})
</script>
</body>
</html>
1.6.网络应用
Vue结合网络数据开发应用。调用服务器获取网络数据。vue结合axios完成网络请求。
axios是功能强大的网络请求库
https://unpkg.com/axios/dist/axios.min.jshttps://unpkg.com/axios/dist/axios.min.js
axios发送网络请求得语法:
axios.get(url?key=value&key2=value2).then(function(result){},function(error){})
axios.post(url,{key:value,key:value}).then(function(result){},function(error){})
我们可以访问第三方得服务器。
2.axios+vue
例: 随机获取笑话
<%--
Created by IntelliJ IDEA.
User: ykq
Date: 2022/5/24
Time: 15:51
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/axios.min.js"></script>
</head>
<body>
<div id="app">
<button @click="getPlay">获取笑话</button>
<ul>
<li v-for="p in plays">{{p}}</li>
</ul>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
plays:[],
},
methods:{
getPlay(){
var _this=this; //
//不能使用this 因为这里得this标识axios对象。
axios.get("https://autumnfish.cn/api/joke/list?num=5").then(function(result){
//先查看axios对象的结构
//console.log(result);
_this.plays=result.data.jokes
})
}
}
})
</script>
</body>
</html>
用户注册:
<%--
Created by IntelliJ IDEA.
User: w
Date: 2022/5/24
Time: 18:25
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="js/axios.min.js"></script>
<script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
<div id="app">
<button @click="register">注册用户</button>
<span v-html="result"></span>
</div>
</body>
<script>
var app= new Vue({
el:"#app",
data:{
result:"",
},
methods:{
register(){
axios.post("https://autumnfish.cn/api/user/reg",{"username":"555"}).then(function(result){
//console.log(result.data);
app.result="<font color='green'>"+result.data+"</font>";
});
}
}
});
</script>
</html>
天知道:
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>
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/tianindex.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="seek"
/>
<button class="input_sub" @click="seek()">
搜 索
</button>
</div>
<div class="hotkey">
<a href="javascript:;" v-for="c in citys" @click="gain(c)">{{c}}</a>
</div>
</div>
<ul class="weather_list">
<li v-for="w in weathers">
<div class="info_type"><span class="iconfont">{{w.type}}</span></div>
<div class="info_temp">
<b>{{w.low}}</b>
~
<b>{{w.high}}</b>
</div>
<div class="info_date"><span>{{w.date}}</span></div>
</li>
</ul>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="../js/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="../js/axios.min.js"></script>
<!-- 自己的js -->
<script>
var app = new Vue({
el:"#app",
data:{
//输入框的数据
city:"",
//最近五天的天气数据
weathers:[],
citys:[]
},
methods:{
seek(){
if(this.citys.indexOf(this.city)==-1){
this.citys.unshift(this.city); //头部插入
}
axios.get("http://wthrcdn.etouch.cn/weather_mini?city="+this.city).then(function(result){
//console.log(result.data.data.forecast);
app.weathers=result.data.data.forecast;
});
this.city="";
if(this.citys.length>10){
this.citys.splice(0,1);
}
},
gain(c){
axios.get("http://wthrcdn.etouch.cn/weather_mini?city="+c).then(function(result){
//console.log(result.data.data.forecast);
app.weathers=result.data.data.forecast;
});
this.city="";
if(this.citys.length>10){
this.citys.splice(0,1);
}
}
}
});
</script>
</body>
</html>
css:
reset.css
body,ul,h1,h2,h3,h4,h5,h6{
margin: 0;
padding: 0;
}
h1,h2,h3,h4,h5,h6{
font-size:100%;
font-weight:normal;
}
a{
text-decoration:none;
}
ul{
list-style:none;
}
img{
border:0px;
}
/* 清除浮动,解决margin-top塌陷 */
.clearfix:before,.clearfix:after{
content:'';
display:table;
}
.clearfix:after{
clear:both;
}
.clearfix{
zoom:1;
}
.fl{
float:left;
}
.fr{
float:right;
}
tianindex.css:
body{
font-family:'Microsoft YaHei';
}
.wrap{
position: fixed;
left:0;
top:0;
width:100%;
height:100%;
/* background: radial-gradient(#f3fbfe, #e4f5fd, #8fd5f4); */
/* background:#8fd5f4; */
/* background: linear-gradient(#6bc6ee, #fff); */
background:#fff;
}
.search_form{
width:640px;
margin:100px auto 0;
}
.logo img{
display:block;
margin:0 auto;
}
.form_group{
width:640px;
height:40px;
margin-top:45px;
}
.input_txt{
width:538px;
height:38px;
padding:0px;
float:left;
border:1px solid #41a1cb;
outline:none;
text-indent:10px;
}
.input_sub{
width:100px;
height:40px;
border:0px;
float: left;
background-color: #41a1cb;
color:#fff;
font-size:16px;
outline:none;
cursor: pointer;
position: relative;
}
.input_sub.loading::before{
content:'';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: url('../img/loading.gif');
}
.hotkey{
margin:3px 0 0 2px;
}
.hotkey a{
font-size:14px;
color:#666;
padding-right:15px;
}
.weather_list{
height:200px;
text-align:center;
margin-top:50px;
font-size:0px;
}
.weather_list li{
display:inline-block;
width:140px;
height:200px;
padding:0 10px;
overflow: hidden;
position: relative;
background:url('../img/line.png') right center no-repeat;
background-size: 1px 130px;
}
.weather_list li:last-child{
background:none;
}
/* .weather_list .col02{
background-color: rgba(65, 165, 158, 0.8);
}
.weather_list .col03{
background-color: rgba(94, 194, 237, 0.8);
}
.weather_list .col04{
background-color: rgba(69, 137, 176, 0.8);
}
.weather_list .col05{
background-color: rgba(118, 113, 223, 0.8);
} */
.info_date{
width:100%;
height:40px;
line-height:40px;
color:#999;
font-size:14px;
left:0px;
bottom:0px;
margin-top: 15px;
}
.info_date b{
float: left;
margin-left:15px;
}
.info_type span{
color:#fda252;
font-size:30px;
line-height:80px;
}
.info_temp{
font-size:14px;
color:#fda252;
}
.info_temp b{
font-size:13px;
}
.tem .iconfont {
font-size: 50px;
}
1.7.综合应用
悦听播放器:
css:
playerIndex.css:
body,
ul,
dl,
dd {
margin: 0px;
padding: 0px;
}
.wrap {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: url("../images/bg.jpg") no-repeat;
background-size: 100% 100%;
}
.play_wrap {
width: 800px;
height: 544px;
position: fixed;
left: 50%;
top: 50%;
margin-left: -400px;
margin-top: -272px;
/* background-color: #f9f9f9; */
}
.search_bar {
height: 60px;
background-color: #1eacda;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
z-index: 11;
}
.search_bar img {
margin-left: 23px;
}
.search_bar input {
margin-right: 23px;
width: 296px;
height: 34px;
border-radius: 17px;
border: 0px;
background: url("../images/zoom.png") 265px center no-repeat
rgba(255, 255, 255, 0.45);
text-indent: 15px;
outline: none;
}
.center_con {
height: 435px;
background-color: rgba(255, 255, 255, 0.5);
display: flex;
position: relative;
}
.song_wrapper {
width: 200px;
height: 435px;
box-sizing: border-box;
padding: 10px;
list-style: none;
position: absolute;
left: 0px;
top: 0px;
z-index: 1;
}
.song_stretch {
width: 600px;
}
.song_list {
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}
.song_list::-webkit-scrollbar {
display: none;
}
.song_list li {
font-size: 12px;
color: #333;
height: 40px;
display: flex;
flex-wrap: wrap;
align-items: center;
width: 580px;
padding-left: 10px;
}
.song_list li:nth-child(odd) {
background-color: rgba(240, 240, 240, 0.3);
}
.song_list li a {
display: block;
width: 17px;
height: 17px;
background-image: url("../images/play.png");
background-size: 100%;
margin-right: 5px;
box-sizing: border-box;
}
.song_list li b {
font-weight: normal;
width: 122px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.song_stretch .song_list li b {
width: 200px;
}
.song_stretch .song_list li em {
width: 150px;
}
.song_list li span {
width: 23px;
height: 17px;
margin-right: 50px;
}
.song_list li span i {
display: block;
width: 100%;
height: 100%;
cursor: pointer;
background: url("../images/table.png") left -48px no-repeat;
}
.song_list li em,
.song_list li i {
font-style: normal;
width: 100px;
}
.player_con {
width: 400px;
height: 435px;
position: absolute;
left: 200px;
top: 0px;
}
.player_con2 {
width: 400px;
height: 435px;
position: absolute;
left: 200px;
top: 0px;
}
.player_con2 video {
position: absolute;
left: 20px;
top: 30px;
width: 355px;
height: 265px;
}
.disc {
position: absolute;
left: 73px;
top: 60px;
z-index: 9;
}
.cover {
position: absolute;
left: 125px;
top: 112px;
width: 150px;
height: 150px;
border-radius: 75px;
z-index: 8;
}
.comment_wrapper {
width: 180px;
height: 435px;
list-style: none;
position: absolute;
left: 600px;
top: 0px;
padding: 25px 10px;
}
.comment_wrapper .title {
position: absolute;
top: 0;
margin-top: 10px;
}
.comment_wrapper .comment_list {
overflow: auto;
height: 410px;
}
.comment_wrapper .comment_list::-webkit-scrollbar {
display: none;
}
.comment_wrapper dl {
padding-top: 10px;
padding-left: 55px;
position: relative;
margin-bottom: 20px;
}
.comment_wrapper dt {
position: absolute;
left: 4px;
top: 10px;
}
.comment_wrapper dt img {
width: 40px;
height: 40px;
border-radius: 20px;
}
.comment_wrapper dd {
font-size: 12px;
}
.comment_wrapper .name {
font-weight: bold;
color: #333;
padding-top: 5px;
}
.comment_wrapper .detail {
color: #666;
margin-top: 5px;
line-height: 18px;
}
.audio_con {
height: 50px;
background-color: #f1f3f4;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.myaudio {
width: 800px;
height: 40px;
margin-top: 5px;
outline: none;
background-color: #f1f3f4;
}
/* 旋转的动画 */
@keyframes Rotate {
from {
transform: rotateZ(0);
}
to {
transform: rotateZ(360deg);
}
}
/* 旋转的类名 */
.autoRotate {
animation-name: Rotate;
animation-iteration-count: infinite;
animation-play-state: paused;
animation-timing-function: linear;
animation-duration: 5s;
}
/* 是否正在播放 */
.player_con.playing .disc,
.player_con.playing .cover {
animation-play-state: running;
}
.play_bar {
position: absolute;
left: 200px;
top: -10px;
z-index: 10;
transform: rotate(-25deg);
transform-origin: 12px 12px;
transition: 1s;
}
/* 播放杆 转回去 */
.player_con.playing .play_bar {
transform: rotate(0);
}
/* 搜索历史列表 */
.search_history {
position: absolute;
width: 296px;
overflow: hidden;
background-color: rgba(255, 255, 255, 0.3);
list-style: none;
right: 23px;
top: 50px;
box-sizing: border-box;
padding: 10px 20px;
border-radius: 17px;
}
.search_history li {
line-height: 24px;
font-size: 12px;
cursor: pointer;
}
.switch_btn {
position: absolute;
right: 0;
top: 0;
cursor: pointer;
}
.right_line {
position: absolute;
left: 0;
top: 0;
}
.video_con video {
position: fixed;
width: 800px;
height: 546px;
left: 50%;
top: 50%;
margin-top: -273px;
transform: translateX(-50%);
z-index: 990;
}
.video_con .mask {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 980;
background-color: rgba(0, 0, 0, 0.8);
}
.video_con .shutoff {
position: fixed;
width: 40px;
height: 40px;
background: url("../images/shutoff.png") no-repeat;
left: 50%;
margin-left: 400px;
margin-top: -273px;
top: 50%;
z-index: 995;
}
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>悦听player</title>
<!-- 样式 -->
<link rel="stylesheet" href="./css/playerIndex.css">
</head>
<body>
<div class="wrap">
<!-- 播放器主体区域 -->
<div class="play_wrap" id="player">
<div class="search_bar">
<img src="images/player_title.png" alt=""/>
<!-- 搜索歌曲 v-model绑定data中keyword变量 searchMusic触发了该方法-->
<input type="text" autocomplete="off" v-model="keyword" @keyup.enter="searchMusic"/>
</div>
<div class="center_con">
<!-- 搜索歌曲列表 -->
<div class='song_wrapper'>
<ul class="song_list">
<li v-for="m in musics"><a style="cursor: pointer" @click="playMusic(m.id)"></a> <b>{{m.name}}</b>
<span v-show="m.mvid!=0"><i @click="playMV(m.mvid)"></i></span></li>
</ul>
<img src="images/line.png" class="switch_btn" alt="">
</div>
<!-- 歌曲信息容器 -->
<div :class="flag?'player_con playing':'player_con'" >
<img src="images/player_bar.png" class="play_bar"/>
<!-- 黑胶碟片 -->
<img src="images/disc.png" class="disc autoRotate"/>
<img :src="musicPic" class="cover autoRotate"/>
</div>
<!-- 评论容器 -->
<div class="comment_wrapper">
<h5 class='title'>热门留言</h5>
<div class='comment_list'>
<dl v-for="c in musicComments">
<dt><img :src="c.user.avatarUrl" alt=""></dt>
<dd class="name">{{c.user.nickname}}</dd>
<dd class="detail">
{{c.content}}
</dd>
</dl>
</div>
<img src="images/line.png" class="right_line">
</div>
</div>
<div class="audio_con">
<!--audio音频标签-->
<audio ref='audio' :src="musicUrl" controls autoplay loop class="myaudio" @pause="zt" @play="bf"></audio>
</div>
<div class="video_con" v-if="mvFlag">
<video controls="controls"></video>
<div class="mask shutoff" @click="closeMV"></div>
</div>
</div>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告(1)查询歌曲 (2)播放歌曲 (3)封面 (4)歌曲得评论 -->
<script src="../js/vue.js"></script>
<!-- 官网提供的 axios 在线地址 -->
<script src="../js/axios.min.js"></script>
<script>
var app = new Vue({
el: ".wrap",
data: {
//搜索关键字
keyword: "",
//搜到到得所有歌曲
musics: [],
//歌曲得播放路径
musicUrl: "",
//歌曲封面
musicPic:"",
//歌曲得评论
musicComments:[],
//判断启动杆是否放下
flag:false,
//判断mv是否显示
mvFlag:false,
//mv得路径
mvUrl:""
},
methods: {
//关闭mv
closeMV(){
this.myFlag=false;
this.mvUrl="";
},
//播放mv
playMV(mid){
//mv得弹出层显示
this.mvFlag=true;
//https://autumnfish.cn/mv/url?id=
axios.get("https://autumnfish.cn/mv/url?id="+mid).then(function(result){
//console.log(result)
app.mvUrl=result.data.data.url;
});
},
//播放
bf(){
this.flag=true;
},
//暂停
zt(){
this.flag=false;
},
//搜索歌曲
searchMusic() {
var that = this;
axios.get("https://autumnfish.cn/search?keywords=" + this.keyword).then(function (result) {
that.musics = result.data.result.songs;
})
},
playMusic(id) {
this.flag=true;//黑蝶滚动
var that = this;
//播放歌曲得路径 但是你也要会。
axios.get("https://autumnfish.cn/song/url?id=" + id).then(function (result) {
that.musicUrl = result.data.data[0].url;
})
//查询歌曲得封面
axios.get("https://autumnfish.cn/song/detail?ids=" + id).then(function (result) {
that.musicPic=result.data.songs[0].al.picUrl;
})
//查询歌曲得评论
axios.get("https://autumnfish.cn/comment/hot?type=0&id="+id).then(function(result){
that.musicComments=result.data.hotComments;
})
}
}
})
</script>
</body>
</html>