JavaScript基础知识
ES6语法规范(结构赋值、模板字符串、箭头函数)
ES6模块化(默认、分别、统一暴露)
包管理器(npm、yarn)
原型、原型链
数组常用方法
axios
promise
1 Vue 简介
渐进式JavaScript框架
简化Dom操作
响应式数据驱动
2 Vue 特点 2.1 组件化模式 采用组件化模式,提高代码复用率,易于维护。
2.2 声明式编码 使用Vue指令,无需直接操作DOM,提高开发效率。
2.3 虚拟DOM+Diff 数据->虚拟DOM->真实DOM。
通过Diff比较判断虚拟DOM和真实DOM的区别,从而更新真实DOM。
3 第一个 Vue 程序
导入开发版本Vue.js
创建Vue实例对象,设置 el
和 data
属性
使用简洁的模板语法把数据渲染到页面上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > {{ message }} </div > <script > var app = new Vue ({ el : '#app' , data : { message : 'Hello Vue!' } }) </script > </body > </html >
4 el 挂载点 el(element:元素),设置挂载点。
作用范围:Vue会管理el选项命中的元素及其内部的后代元素。
选择器:可以使用其他选择器,但是建议使用ID选择器。
dom元素:可以使用其他的双标签,但不能使用 html
和 body
。
5 data 数据对象
Vue用到的数据定义在data中。
data中可以写复杂类型的数据。
渲染复杂的数据类型时,遵循js语法即可。
6 Vue 指令 6.1 本地应用——计数器 6.1.1 本地应用 v-text 指令 设置标签的文本值(textContent)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <h2 v-text ="message+'!'" > 地址:</h2 > <h2 > 地址:{{message+"!"}}</h2 > </div > <script > var hello = new Vue ({ el : '#app' , data : { message : "深圳市南山区" } }) </script > </body > </html >
6.1.2 本地应用 v-html 指令 设置标签的innerHTML,内容中有html结构会被解析为标签。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <h2 v-html ="content" > </h2 > </div > <script > var hello = new Vue ({ el : '#app' , data : { content : "<a href='https://www.baidu.com'>百度</a>" } }) </script > </body > </html >
6.1.3 本地应用 v-on 指令 为元素绑定事件,事件名不需要写on,指令可以简写为@。
1 2 3 4 5 6 <div > <input type ="button" value ="事件绑定" v-on:click ="doIt" > <input type ="button" value ="事件绑定" v-on:mouseenter ="doIt" > <input type ="button" value ="事件绑定" v-on:dblclick ="doIt" > <input type ="button" value ="事件绑定" @dbclick ="doIt" > </div >
1 2 3 4 5 6 7 8 var app = new Vue ({ el : "#app" , methods :{ doIt :function ( ){ } } })
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="button" value ="v-on指令" @click ="doIt" > </div > <script > var hello = new Vue ({ el : '#app' , methods : { doIt :function ( ){ alert ("Do It!" ) } } }) </script > </body > </html >
6.1.4 计数器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="button" value ="-" @click ="sub" > <span v-text ="count" > </span > <input type ="button" value ="+" @click ="add" > </div > <script > var hello = new Vue ({ el : '#app' , data : { count : 0 }, methods : { sub :function ( ){ if (this .count > 0 ) { this .count --; }else { alert ("不能再减了!" ) } }, add :function ( ){ if (this .count < 5 ) { this .count ++; }else { alert ("不能再加了!" ) } } } }) </script > </body > </html >
6.2 本地应用——图片切换 6.2.1 本地应用 v-show 指令 根据布尔值切换显示状态(适用于频繁切换的元素)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="button" value ="切换显示状态" @click ="toggleShow" > <img src ="./Gitee.png" alt ="jpg" v-show ="isShow" > <img src ="./GitHub.png" alt ="jpg" v-show ="age>=18" > </div > <script > var hello = new Vue ({ el : '#app' , data : { isShow : true , age : 17 }, methods : { toggleShow :function ( ){ this .isShow = !this .isShow ; } } }) </script > </body > </html >
6.2.2 本地应用 v-if 指令 根据表达式真假,切换元素的显示和隐藏(操作dom元素,对性能消耗大)。
本质是操作dom元素来切换显示状态,表达式为真时,元素存在于dom树中,为假时,从dom树中移除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="button" value ="切换显示" @click ="toggleShow" > <p v-if ="isShow" > Hello Vue by v-if</p > <p v-show ="isShow" > Hello Vue by v-show</p > </div > <script > var hello = new Vue ({ el : '#app' , data : { isShow : true , }, methods : { toggleShow :function ( ){ this .isShow = !this .isShow ; } } }) </script > </body > </html >
6.2.3 本地应用 v-bind 指令 设置元素的属性(比如src,title,class)。
v-bind:属性=表达式(v-bind可省略)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > <style > .active { border : 1px solid red; } </style > </head > <body > <div id ="app" > <img :src ="imgSrc" alt ="" > <br /> <img :src ="imgSrc" alt ="" :title ="imgTitle+'!!!'" > <br /> <img :src ="imgSrc" alt ="" :class ="{active:isActive}" @click ="toggleActive" > </div > <script > var hello = new Vue ({ el : '#app' , data : { isActive : false , imgSrc : "./Gitee.png" , imgTitle : "Gitee" }, methods : { toggleActive :function ( ){ this .isActive = !this .isActive ; } } }) </script > </body > </html >
6.2.4 图片切换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > <style > .active { border : 1px solid red; } </style > </head > <body > <div id ="app" > <img :src ="imgArr[index]" alt ="" > <a href ="#" @click ="prev" v-show ="index!=0" > 上一张</a > <a href ="#" @click ="next" v-show ="index<imgArr.length-1" > 下一张</a > </div > <script > var hello = new Vue ({ el : '#app' , data : { isActive : false , imgArr : ['./Gitee.png' , './GitHub.png' , './weixin.png' , './QQ.png' ], index : 0 }, methods : { prev :function ( ){ if (this .index > 0 ){ this .index --; } }, next :function ( ){ if (this .index < this .imgArr .length -1 ){ this .index ++; } } } }) </script > </body > </html >
6.3 本地应用——小黑记事本 6.3.1 本地应用 v-for 指令 根据数据生成列表结构。
数组经常和 v-for
结合使用。
语法是( item, index) in 数据
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <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}} {{ item }} </li > </ul > <h3 v-for ="item in vegetables" :title ="item.name" > {{ item.name }} </h3 > </div > <script > var hello = new Vue ({ el : '#app' , data : { arr : ["北京" , "上海" , "广州" , "深圳" ], vegetables : [ {name : "西红柿" }, {name : "西兰花" } ] }, methods : { add :function ( ){ this .vegetables .push ({name : "西葫芦" }); }, remove :function ( ){ this .vegetables .shift (); } } }) </script > </body > </html >
6.3.2 本地应用 v-on 补充 传递自定义参数,事件修饰符 (.修饰)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="button" value ="点我" @click ="doIt(666, 'adt')" > <input type ="text" @keyup.enter ="saiHi" > </div > <script > var hello = new Vue ({ el : '#app' , methods : { doIt :function (p1, p2 ){ alert (p1+p2); }, saiHi :function ( ){ alert ("你好!" ); } } }) </script > </body > </html >
6.3.3 本地应用 v-model 指令 获取和设置表单元素的值(双向数据绑定)。
绑定的数据会和表单元素值相关联。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="button" value ="设置message" @click ="setMessage" > <input type ="text" v-model ="message" @keyup.enter ="getMessage" > <h3 > {{ message }}</h3 > </div > <script > var hello = new Vue ({ el : '#app' , data : { message : "深圳市南山区" }, methods : { getMessage :function ( ){ alert (this .message ); }, setMessage :function ( ){ this .message = "广东省" ; } } }) </script > </body > </html >
6.3.4 小黑记事本 6.3.4.1 新增
生成列表结构(v-for 数组)。
获取用户输入(v-model)。
回车,新增数据(v-on,.enter,添加数据)。
6.3.4.2 删除
数据改变,和数据绑定的元素也会同步改变。
事件可接受自定义参数。
点击删除指定内容(v-on,splice).
6.3.4.3 统计
统计信息个数(v-text length)
基于数据的开发方式。
6.3.4.4 清空 点击清除所有信息(v-on,清空数组)。
6.3.4.5 隐藏 没有数据时,隐藏元素(v-show,v-if 数组非空)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="text" v-model ="items" placeholder ="请输入待办事项" @keyup.enter ="addlist" > <ul > <li v-for ="(item,index) in list" > {{ index+1 }} {{item}} <input type ="button" value ="X" @click ="remove(index)" > </li > </ul > <span v-show ="list.length!=0" > <strong > {{ list.length }} 个待办 </strong > </span > <input type ="button" value ="清空待办" v-show ="list.length!=0" @click ="removeAll" > </div > <script > var hello = new Vue ({ el : '#app' , data : { list : ["写代码" , "吃饭" , "睡觉" ], items : "" , }, methods : { addlist :function ( ){ this .list .push (this .items ); }, remove :function (index ){ this .list .splice (index, 1 ); }, removeAll :function ( ){ this .list = []; } } }) </script > </body > </html >
6.4 网络应用 6.4.1 axios 基本使用 axios 是一个功能强大的网络请求库。
axios
必须先导入再使用。
使用 get
或 post
方法即可发送对应的请求。
then
方法中的回调函数会在请求成功或失败时触发。
通过回调函数的形参可以获取响应内容,或错误信息。
1 2 3 4 5 <script src ="https://unpkg.com/axios/dist/axios.min.js" > </script > // get 语法 axios.get(地址?key1=value1&key2=value2).then(function(reponse){},function(err){}) // post 语法 axios.post(地址,{key1:value1,key2:value2}).then(function(reponse){},function(err){})
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <script src ="https://unpkg.com/axios/dist/axios.min.js" > </script > <title > Vue</title > </head > <body > <input type ="button" value ="get请求" class ="get" > <input type ="button" value ="post请求" class ="post" > <script > document .querySelector (".get" ).onclick = function ( ){ axios.get ("https://autumnfish.cn/api/joke/list?num=3" ).then (function (response ) { console .log (response); },function (err ){ console .log (err); }) }; document .querySelector (".post" ).onclick = function ( ){ axios.post ("https://autumnfish.cn/api/user/reg" , {username : "jack1122654" }).then (function (response ) { console .log (response); },function (err ){ console .log (err); }) }; </script > </body > </html >
6.4.2 axios 加 vue
axios
回调函数中的 this
已经改变,无法访问到 data
中数据。
把 this
保存起来,回调函数中直接使用保存的 this
即可。
和本地应用最大的区别就是改变了数据来源。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <script src ="https://unpkg.com/axios/dist/axios.min.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="button" value ="获取笑话" @click ="getJoke" > <p > {{ jokes }}</p > </div > <script > var hello = new Vue ({ el : '#app' , data : { jokes : "笑话" , }, methods : { getJoke :function ( ){ var that = this ; axios.get ("https://autumnfish.cn/api/joke" ).then (function (response ) { that.jokes = response.data ; console .log (response.data ); },function (err ){ console .log (err); }); } } }) </script > </body > </html >
6.4.3 天知道
应用的逻辑代码建议和页面分离,使用单独的 js
文件编写。
axios
回调函数中 this
指向改变了,需要额外保存一份。
服务器返回的数据比较复杂时,获取的时候需要注意层级结构。
6.4.3.1 回车查询
按下回车(v-on,keyup.enter)
查询数据(axios 接口,v-model)
渲染数据(v-for 数组 that)
6.4.3.2 点击查询
点击城市(v-on 自定义参数)。
查询数据(this.方法())。
渲染数据。
自定义参数让代码复用性更高。
methods
中定义的方法内部,可以通过 this
关键字点出其他的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 <!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" > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <script src ="https://unpkg.com/axios/dist/axios.min.js" > </script > <title > Vue</title > </head > <body > <div id ="app" > <input type ="text" v-model ="city" placeholder ="请输入要查询的城市" @keyup.enter ="getWeather" > <input type ="button" value ="搜索" @click ="getWeather" > <a href ="javascript:;" @click ="changeCity('北京')" > 北京</a > <a href ="javascript:;" @click ="changeCity('上海')" > 上海</a > <a href ="javascript:;" @click ="changeCity('广州')" > 广州</a > <a href ="javascript:;" @click ="changeCity('深圳')" > 深圳</a > <ul > <li v-for ="item in weatherList" > {{item.date}} | {{item.fengxiang}} | {{item.high}} | {{item.low}} | {{item.type}}</li > </ul > </div > <script > var hello = new Vue ({ el : '#app' , data : { city : "" , weatherList : [] }, methods : { getWeather :function ( ){ var that = this ; axios.get ("http://wthrcdn.etouch.cn/weather_mini?city=" +this .city ).then (function (response ) { that.weather = response.data .data .forecast ; that.weatherList = response.data .data .forecast ; console .log (response.data ); },function (err ){ console .log (err); }); }, changeCity :function (cityName ){ this .city = cityName; this .getWeather (); } } }) </script > </body > </html >
6.5 综合应用 6.5.1 音乐查询
按下回车(v-on keyup.enter)。
查询数据(axios接口 v-model)。
渲染数据(v-for 数组 that)。
6.5.2 音乐播放
点击播放(v-on)。
歌曲地址获取(接口 歌曲id)。
歌曲地址设置(v-bind)。
歌曲id依赖于歌曲搜索的结果,对于不用的数据也需要关注。
6.5.3 歌曲封面
点击播放(v-on 增加逻辑)。
歌曲封面获取(接口 歌曲id)。
歌曲封面设置(v-bind)。
6.5.4 歌曲评论
6.5.5 播放动画
监听音乐播放(v-on play)。
监听音乐暂停(v-on pause)。
操纵类名(v-bind 对象)。
audio标签的play事件会在音频播放的时候触发。
audio标签的pause事件会在音频暂停的时候触发。
通过对象的方式设置类名,类名生效与否取决于后面值得真假。
6.5.6 播放 mv
6.5.6.1 index.css 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 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 ; } .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 ; }
6.5.6.2 main.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 var app = new Vue ({ el : "#player" , data : { qurey :"" , musicList :[], musicUrl :"" , musicDetail :"" , hotComments :[], isPlaying :false , isShow : false , mvUrl :"" }, methods : { searchMusic :function ( ){ var that = this ; axios.get ("https://autumnfish.cn/search?keywords=" +this .qurey ) .then (function (response ){ that.musicList = response.data .result .songs ; }, function (err ){console .log (err);}); }, musicPlayer :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.musicDetail = response.data .songs [0 ].al .picUrl ; },function (err ){console .log (err);}); axios.get ("https://autumnfish.cn/comment/hot?type=0&id=" +musicId) .then (function (response ){ that.hotComments = response.data .hotComments ; }, function (err ){console .log (err);}); }, play :function ( ){ this .isPlaying = true ; }, pause : function ( ){ this .isPlaying = false ; }, 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 ; this .isPlaying = false ; }, function (err ){console .log (err);}); }, hide :function ( ){ this .isShow = false ; this .mvUrl = "" ; } } });
6.5.6.3 music.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 <!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/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 ="qurey" @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 ="musicPlayer(item.id)" > </a > <b > {{item.name}}</b > <span v-if ="item.mvid!=0" @click ="playMv(item.mvid)" > <i > </i > </span > </li > </li > </ul > <img src ="images/line.png" class ="switch_btn" alt ="" > </div > <div class ="player_con" :class ="{playing:isPlaying}" class ="playing" > <img src ="images/player_bar.png" class ="play_bar" /> <img src ="images/disc.png" class ="disc autoRotate" /> <img :src ="musicDetail" class ="cover autoRotate" /> </div > <div class ="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 ="isShow" style ="display: none;" > <video :src ="mvUrl" controls ="controls" > </video > <div class ="mask" @click ="hide" > </div > </div > </div > </div > <script src ="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js" > </script > <script src ="https://unpkg.com/axios/dist/axios.min.js" > </script > <script src ="./js/main.js" > </script > </body > </html >