Vue基础
vue是JavaScript框架,它简化了dom操作,是响应式数据驱动
第一个vue程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
</head>
<body>
<div id="app">
{{ message }}
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
//先引入vue.js
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
</script>
</body>
</html>
el 挂载点
通过css选择器设置vue实例管理的元素,设置完成过后,el管理元素内部使用两个大括号中的内容就会被data中的内容替换
需要注意的几个问题:
- 被渲染的内容一定要在元素内部
- el选中的元素后代也会被渲染,可以任意嵌套其他标签
- 除了id选择器,class选择器等其他选择器也行
- 只能写在双标签内部,单标签不行。html和bbody标签也不行
data 数据对象
- vue中用到的数据定义在data中
- data中可以写复杂数据类型
- 渲染复杂类型数据时,遵守js语法即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
</head>
<body>
<div id="app" class="app">
{{ message }}
<h2>
{{ school.name }}
{{ school.remark }}
</h2>
<ul>
<li>{{ }}</li>
</ul>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Lychee!',
school:{
name:"lychee",
remark:"my lovly wife!"
}
},
campus:["福州","北京"]
})
</script>
</body>
</html>
本地应用
vue指令是以**v-**开头的一组特殊语法
v-text
{{}}:这个叫插值表达式
设置标签的文本值
<div id="app" >
<h2 v-text="message"></h2>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
message:"lychee"
}
})
</script>
如果这样写,h2标签中会全部被替换,如果想部分替换
我们可以使用下面的方法:
<div id="app" >
<h2 v-text="message"></h2>
<h2>{{ message }}</h2>
//只有大括号内部会被替换,其他会被保留
</div>
v-html
v-html作用是设置元素的innerHTML
html结构会被解析为标签
<div id="app" >
<h2 v-html="content"></h2>
</div>
<script>
var app = new Vue({
el : "#app" ,
data: {
content:"<a href = '#''>荔枝</a>"
}
})
</script>
v-on
为元素绑定事件
事件名不需要写on
指令可以简写为@
绑定的方法定义在methods属性中
方法内部通过this关键字可以访问定义在data中的数据
<div id="app" >
<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="v-on简写" @dblclick="doIt">
<h2 @click="changefood">{{ food }}</h2>
</div>
<script>
var app = new Vue({
el:"#app",
data:{
food:"美味西兰花"
},
methods:{
doIt:function(){
alert("do it");
},
changefood:function(){
this.food+="好好吃!";
}
}
})
</script>
例子:计数器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础---计数器</title>
</head>
<body>
<div id="app" >
<div class="input-num">
<button @click="sub">
-
</button>
<span> {{ num }} </span>
<button @click="add">
+
</button>
</div>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
num:1
},
methods:{
add:function(){
if(this.num<10){
this.num++;
}else{
alert("别点了别点了");
}
},
sub:function(){
if(this.num>0){
this.num--;
}else{
alert("别点了别点了")
}
}
}
});
</script>
</body>
</html>
v-show
根据表达式的真假,切换元素的显示或隐藏
原理是修改元素的display,实现显示隐藏
指令后面的内容,最终都会被解析为布尔值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
</head>
<body>
<div id="app" >
<input type="button" value="切换显示状态" @click="changeIsShow">
<img v-show="isShow" src="" alt="">
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
isShow:true
},
methods:{
changeIsShow:function(){
this.isShow=!this.isShow;
}
}
});
</script>
</body>
</html>
v-if
根据表达式的真假,切换元素的显示和隐藏(操纵dom元素)
和v-show的区别:一个操纵样式(v-show),一个操纵dom树(v-if)
操纵dom树对性能消耗比较大
频繁的切换使用v-show,反之使用v-if,前者切换消耗较小
v-bind
设置元素的属性(比如:src,title,class)
完整写法: v-bind:属性名
简写的话直接省略v-bind,只保留**:属性名**
需要动态增删的class建议使用对象的方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
<style>
.active{
border : 1px solid red;
}
</style>
</head>
<body>
<div id="app" >
<img v-bind:src="imgSrc">
<br>
<img :title="imgTitle+'!!!'" :class="isActive?active:''" @click="toggleActive">
<img :title="imgTitle+'!!!'" :class="{active:isActive}" @click="toggleActive">
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
imgSrc:"",
imgTitle:"图片",
isActive:false,
},
methods:{
toggleActive:function(){
this.isActive = !this.isActive;
}
}
});
</script>
</body>
</html>
例子:图片切换
列表数据用数组保存
v-bind指令可以设置元素属性,比如src
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
<style>
.active{
border : 1px solid red;
}
</style>
</head>
<body>
<div id="app" >
<!-- 图片 -->
<img :src="imgArr[index]">
<!-- 左箭头 -->
<a href="#" @click="prev" v-show="index!=0" class="left">
<img src="./images/prev.png" alt="前一张">
</a>
<!-- 右箭头 -->
<a href="#" @click="next" v-show="index<imgArr.length-1>" class="right">
<img src="./images/prev.png" alt="后一张">
</a>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
imgArr:[""],
index=0
},
methods:{
prev:function(){
this.omdex--;
},
next:function(){
this.index++;
}
}
});
</script>
</body>
</html>
v-for
根据数据生成列表结构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
</head>
<body>
<div id="app" >
<ul>
<li v-for="item in thg">
荔枝小姐最喜欢做的几件事情 {{ item }}
</li>
<li v-for="(food,index) in arr">
{{ index+1 }} 荔枝小姐最喜欢吃的几样东西 {{ food }}
</li>
</ul>
<h2 v-for="dish in dishes" :title="dish.name">
{{ dish.name }}
</h2>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
thg:["做饭","读书","旅行"],
arr:["面包","甜食","上海青","茶点"],
dishes:[
{name:"清炒西兰花"},
{name:"水煮蛋撒黑胡椒"}
]
},
methods:{
}
});
</script>
</body>
</html>
v-model
获取和设置表单元素的值(双向数据绑定)
绑定的数据会和表单元素值相关联
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
</head>
<body>
<div id="app" >
<input type="button" value="change message" @click="setM">
<input type="text" v-model="message" @keyup.enter="getM">
<h2>{{ message}}</h2>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"lychee"
}
});
</script>
</body>
</html>
案例:记事本
新增数据
1,生成列表结构(v-for)
2,获取用户输入
3,回车,新增元素
删除
1,点击删除指定内容(v-on splice 索引)
splice:根据索引删除指定元素
统计
1,统计信息个数
2,显示的数字就是数组的长度
删除
- 结合数据对list中内容进行删除
记事本代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
</head>
<body>
<!-- 主体区域 -->
<section id="todoapp">
<!-- 输入框 -->
<header class="header">
<h1>荔枝の记事本</h1>
<input v-model="inputValue" @keyup.enter="add" autofocus="autofocus" autocomplete="off" placeholder="宝贝今天都要干点啥" class="new-todo" >
</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>
<lable> {{item}}</lable>
<button class="destroy" @click="remove(index)"></button>
</div>
</li>
</ul>
</section>
<!-- 统计和清空 -->
<footer class="footer">
<span calss="todo-count" v-if="list.length!=0">
<strong> {{list.length}} </strong>items left
</span>
<button v-show="list.length" class="clear-completed" @click="clear">Clear</button>
</footer>
</section>
<!-- 底部 -->
<footer class="info">
</footer>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<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);
},
remove:function(index){
this.list.splice(index,1);
},
clear:function(){
this.list=[];
}
}
})
</script>
</body>
</html>
网络应用
结合网络数据开发应用
axios:网络请求库
axios+vue:两者结合一起使用
axios
功能强大的网络请求库
axios必须先导入才可以使用
使用get或者post方法即可发送对应的请求
then方法中的回调函数会在请求成功或者失败时触发
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
axios.get("url?key1=value1&key2=value2").then(function(response){},function(err){})
axios.post("url?key1=value1&key2=value2").then(function(response){},function(err){})
get方式发送数据用问号和&
post发送数据使用对象的方式:{key:value}
axios+vue
methods中使用axios给this改值会造成undefined的结果,需要新建一个变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
</head>
<body>
<div id="app">
<input type="button" value="获取笑话" class="get" @click="getjoke">
<p>{{joke}} </p>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var app=new Vue({
el:"#app",
data:{
joke:""
},
methods:{
getjoke:function(){
var that = this;
axios.get("https://api.vvhan.com/api/xh").then(function(res){
that.joke=res.data;
},function(err){
})
}
}
});
</script>
</body>
</html>
网络应用:天气查询
- 回车查询
按下回车(v-on .enter)
查询数据(axios,v-model)
渲染数据(v-for that) - 点击查询
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue基础</title>
</head>
<body>
<div id="app">
<input type="text" v-model="city" @keyup.enter="searchWeather" placeholder="输入你要查询地方的天气">
<button>搜索</button>
<div class="hotkeys">
<a href="#" @click="changeweather('北京')">北京</a>
<a href="#" @click="changeweather('福州')">福州</a>
<a href="#" @click="changeweather('新乡')">新乡</a>
</div>
<ul class="weather_list">
<li v-for="item in weatherlist">
<div><span> {{ item.type }}</span></div>
<div>
<b> {{item.low}} </b>
~
<b> {{item.high}} </b>
</div>
<div> <span> {{item.date}} </span></div>
</li>
</ul>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/axios/0.1.0/axios.min.js"></script>
<script src="./main.js"></script>
</body>
</html>
综合应用
- 歌曲搜索
- 歌曲播放
- 歌曲封面
- 歌曲评论
- 播放动画
- 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>Document</title>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/axios/0.1.0/axios.min.js"></script>
<script src="./main.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-resource@1.5.1"></script>
<!-- 滚动 -->
<style src="style.css"></style>
<script src="iscroll.js"></script>
</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" v-model.trim="search" @keyup.enter="searchMusic" />
</div>
<div class="center_con">
<div class="song_wrapper">
<transition-group
name="list"
tag="ul"
class="song_list"
v-on:after-enter="afterEnter"
>
<li
v-for="(item,index) in musicList"
:key="index"
@dblclick="playMusic(item)"
:style="{transitionDelay:index*10+'ms'}"
>
{{ item.name }}--{{ item.artists[0].name }}
</li>
</transition-group>
</div>
<div class="player_con">
<img
src="images/player_bar.png"
class="play_bar"
:class="{isPlay:isPlay}"
/>
<!-- 黑胶碟片 -->
<img
src="images/disc.png"
class="disc autoRotate"
:class="{playing:isPlay}"
/>
<img
:src="picUrl?picUrl:'./images/cover.png'"
class="cover autoRotate"
:class="{playing:isPlay}"
/>
</div>
<div class="comment_list">
<div>
<dl v-for="(item,index) in commentList" :key="index">
<dt><img :src="item.user.avatarUrl" alt="" /></dt>
<dd class="name">{{ item.user.nickname }}</dd>
<dd class="detail">{{ item.content }}</dd>
</dl>
</div>
</div>
</div>
<div class="audio_con">
<audio
:src="musicUrl"
controls
autoplay
loop
@play="play"
@pause="pause"
class="myaudio"
></audio>
</div>
</div>
</div>
</body>
</html>
// var app = new Vue({
// el:"#player",
// data:{
// query:"",
// musiclist:[]
// },
// methods: {
// searchmusic:function(){
// var that = this;
// axios.get("https://autumnfish.cn/search?keywords="+this.query).then(function(res){
// console.log(res.result.songs) ;
// that.musiclist=res.result.songs
// },function(err){
// console.log(err) })
// },
// }
// })
let app = new Vue({
el: '#player',
data: {
// 搜索内容
search: '',
// 歌曲列表
musicList: [],
// 歌曲地址
musicUrl: '',
// 歌曲封面url
picUrl: '',
// 是否播放
isPlay: false,
// 评论数组
commentList: [],
// mvUrl
mvUrl: '',
// 滚动
myScroll: undefined,
// 左边滚动
leftScroll: undefined
},
mounted() {
this.myScroll = new IScroll('.comment_list', {
mouseWheel: true,
scrollbars: true
})
this.leftScroll = new IScroll('.song_wrapper', {
mouseWheel: true
})
},
updated() {
this.myScroll.refresh()
this.leftScroll.refresh()
},
methods: {
// 动画钩子
afterEnter(e) {
e.style = ''
},
searchMusic() {
// 清空数组
this.musicList = []
this.$http
.get('https://autumnfish.cn/search?keywords=' + this.search)
.then(
res => {
// 赋值歌曲数据
this.musicList = res.body.result.songs
},
err => {}
)
},
// 动画钩子
afterEnter(el) {
el.style = ''
},
// 放歌
playMusic(item) {
// 获取歌曲url
// var that=this;
this.$http.get('https://autumnfish.cn/song/url?id=' + item.id).then(
res => {
// 赋值歌曲url
that.musicUrl = res.body.data[0].url
},
err => {}
)
// 获取 封面url
this.$http
.get('https://autumnfish.cn/album?id=' + item.album.id)
.then(
res => {
// console.log(res);
this.picUrl = res.body.album.picUrl
},
err => {}
)
// 获取评论
this.$http
.get('https://autumnfish.cn/comment/hot?type=0&id=' + item.id)
.then(
res => {
// console.log(res)
this.commentList = res.body.hotComments
},
err => {}
)
// 获取mv
this.$http.get('https://autumnfish.cn/mv/url?id=' + item.mvid).then(
res => {
// console.log(res);
this.mvUrl = res.body.data.url
},
err => {}
)
},
// 歌曲播放
play() {
console.log('play')
this.isPlay = true
},
// 歌曲暂停
pause() {
console.log('pause')
this.isPlay = false
}
}
})