Vue入门

一心想做后端,对于前端是不太乐意去做的,但基本的了解还是需要的。去年Java Web课程作业项目,就是前后端全包,不过那时前端用的还是传统的JSP,着实感觉不太舒服,学过SpringBoot了,使用了Thymeleaf,体会到开发的便捷,认识到了前后端分离,越发感到之前的开发模式是该被取代了。

终于有机会认识前端的一些东西了,本来我的这个博客框架就与前端脱不开关系,Node.jsnpm这些都是我博客搭建的基础,这次来简单入门Vue

参考

提要

必要知识:前端三剑客(HTML、CSS、JS)+ Ajax

开发环境:VSCode + Live Server、Chrome

推荐VSCode插件:Auto Close Tag、Auto Rename Tag、Vetur、根据需要参考 VScode插件推荐(全面)

Live Server 简单使用说明:使用Live Server主要原因是开启本地服务并在保存时刷新页面,方便调试,在VSCode需要使用Live Server 页面右键选择Open with Live ServerStop Live Server

最后会放上我的全部源码链接,希望有帮助。

安装

官方说的非常清楚了新手入门使用

1
2
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>

1
2
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.staticaly.com/npm/vue"></script>

认识Vue

Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:

官方示例

1
2
3
<div id="app">
{{ message }}
</div>

1
2
3
4
5
6
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})

注意上面是在html中,下面在js中

简单理解,声明app通过eldiv-app绑定,这时div-appapp-Vue同属于一个域,data类似声明数据(key-value),通过{{x}},取值

基本

v-text:显示文本,替换问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="text">
{{message}}
<h2 v-text="message+'!'">测试拼接</h2> <!-- 结果:message! -->
<h2 v-text="info+'?'">测试拼接</h2> <!-- 结果:info? -->
<h2>拼接{{message}}</h2> <!-- 结果:拼接message -->
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var text=new Vue({
el:"#text",
data:{
message:"text显示",
info:"信息展示"
}
})
</script>

v-html:显示文本,若是html元素则解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="html">	<!-- content为<a>超链接 -->
<p v-html="content"></p> <!-- 解析成超链接 -->
<p v-text="content"></p> <!-- 解析成超链接文本 -->
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var html=new Vue({
el:"#html",
data:{
content:"<a href='https:/wnhyang.github.io'>博客</a>"
}
})
</script>

v-on:事件处理,可用@代替,函数如下methods部分,在Chrome检查控制台查看

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
<div id="on">
<input type="button" value="v-on指令" v-on:click="doIt"/>
<input type="button" value="@指令" v-on:click="doIt"/>
<input type="button" value="双击" @dblclick="doIt"/>
<h2 @click="changeFood">{{food}}</h2>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var on=new Vue({
el:"#on",
data:{
food:"西红柿"
},
methods:{
doIt:function(){
alert("doit");
},
changeFood(){
console.log(this.food);
this.food+="如果!"
}
},
})
</script>

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
<div id="show">
<input type="button" value="切换显示状态" @click="changeIsShow">
<input type="button" value="累加年龄" @click="addAge">
<img v-show="isShow" width="100" src="./img/123.jpg" alt="">
<img v-show="age>=18" width="100" src="./img/123.jpg" alt="">
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var show=new Vue({
el:"#show",
data:{
isShow:false,
age:17
},
methods:{
changeIsShow:function(){
this.isShow=!this.isShow;
},
addAge:function(){
this.age++;
}
},
})
</script>

v-if:状态,直接在或不在,区分与v-show,发现v-if直接影响整个元素,不是v-show改变状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div id="ifapp">
<input type="button" value="切换显示" @click="toggleIsShow">
<p v-if="isShow">v-if好吗</p>
<p v-show="isShow">v-show好吗</p>
<h2 v-if="temperature>=35">热死了</h2>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var ifapp=new Vue({
el:"#ifapp",
data:{
isShow:false,
temperature:40
},
methods:{
toggleIsShow:function(){
this.isShow=!this.isShow;
}
},
})
</script>

v-bind:绑定,作用于元素属性,可简写为:属性,三元表达式或"{active:isActive}",推荐后者

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
    <style>
.active{
border: 1px solid red;
}
</style>

<div id="bind">
<img width="100" v-bind:src="imgSrc" alt="">
<br/>
<img width="100" :src="imgSrc" :title="imgTitle+'!!!'" alt="" :class="isActive?'active':''" @click="toggleActive">
<br/>
<img width="100" :src="imgSrc" :title="imgTitle+'!!!'" alt="" :class="{active:isActive}" @click="toggleActive">
</div>

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var bind=new Vue({
el:"#bind",
data:{
imgSrc:"https://cn.vuejs.org/images/logo.png",
imgTitle:"Vue",
isActive:false
},
methods:{
toggleActive(){
this.isActive=!this.isActive;
}
}
})
</script>

v-for:循环,看下示例即可

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
<div id="forapp">
<input type="button" value="添加数据" @click="add"/>
<input type="button" value="移除数据" @click="remove"/>
<ul>
<li v-for="(item,index) in arr">
{{index}}Vue:{{item}}
</li>
</ul>
<h2 v-for="item in vegetables" v-bind:title="item.name">
{{item.name}}
</h2>
</div>

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var forapp=new Vue({
el:"#forapp",
data:{
arr:["北京","上海","广州","深圳"],
vegetables:[
{name:"西红柿炒鸡蛋"},
{name:"凉拌黄瓜"}
]
},
methods:{
add:function(){
this.vegetables.push({name:"炒土豆丝"});
},
remove:function(){
this.vegetables.shift();
}
}
})
</script>

v-model:双向绑定,如下,div-modelapp与modelapp-Vue域同步改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id=modelapp>
<input type="button" value="修改message" @click="setM"/>
<input type="text" v-model="message" @keyup.enter="getM"/>
<h2>{{message}}</h2>
</div>

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var modelapp=new Vue({
el:"#modelapp",
data:{
message:"Vue"
},
methods:{
getM:function(){
alert(this.message);
},
setM:function(){
this.message="VueDemo";
}
},
})
</script>

实例

计数器

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
<div id="counter">
<button @click="sub">-</button>
<span>{{num}}</span>
<button @click="add">+</button>
</div>

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var counter=new Vue({
el:"#counter",
data:{
num:1
},
methods:{
add:function(){
console.log('add');
if(this.num<10){
this.num++;
}else{
alert('别点了,最大了');
}
},
sub:function(){
console.log('sub');
if(this.num>0){
this.num--;
}else{
alert('别点了,最小了');
}
}
},
})
</script>

记事本

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
   <div id="todoapp">
<header>
<h1>
Vue记事本
</h1>
<input v-model="inputValue" @keyup.enter="add" type="text" placeholder="输入"/>
</header>

<section class="main">
<ul>
<li v-for="(item,index) in list">
<div>
<span>{{index+1}}.</span>
<label>{{item}}</label>
<button @click="remove(index)">x</button>
</div>

</li>
</ul>
</section>

<footer>
<span v-if="list.length!=0">总数:{{list.length}}</span>
<button @click="clear" v-show="list.length!=0">Clear</span>
</footer>
</div>

<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>
<script>
var todoapp=new Vue({
el:"#todoapp",
data:{
list:["写代码","吃饭","睡觉"],
inputValue:"content",
},
methods:{
add:function(){
this.list.push(this.inputValue);
},
remove:function(index){
console.log("删除");
console.log(index);
this.list.splice(index,1)
},
clear:function(){
this.list=[];
}
}
})
</script>

axios

简单的说:Ajax的封装版,简单实用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<input type="button" value="get" class="get"/>
<input type="button" value="post" class="post"/>

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
// 用的是js呢
document.querySelector(".get").onclick = function() {
axios.get('https://autumnfish.cn/api/joke/list?num=6').then(function(response) {
console.log(response.data); //好像是data吧
}, function(error) {
console.log(error);
})
}

document.querySelector(".post").onclick = function() {
axios.post('https://autumnfish.cn/api/user/reg',{username:"西兰花10"})
.then(function(response){
console.log(response);
},function(error) {
console.log(error);
})
}
</script>

用到在线API:https://autumnfish.cn/api/joke/list?num=6 获取6条笑话,https://autumnfish.cn/api/user/reg 注册用户

vue-axios

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
<div id="app">
<input type="button" value="获取笑话" @click="getJoke"/>
<p>{{joke}}</p>
</div>

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>

<script>
var app=new Vue({
el:"#app",
data:{
joke:"笑话"
},
methods:{
getJoke:function(){
console.log(this.joke);
var that=this;
axios.get('https://autumnfish.cn/api/joke')
.then(function(response){
console.log(response.data);
that.joke=response.data;
// this.joke=response.data;
},function(error){
console.log(error);
})
}
}
})
</script>

仔细看:this,that

实例

查天气

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
<div id="app">
<input @keyup.enter="searchWeather" v-model="city" type="text" placeholder="输入地区查天气"/>
<button @click="searchWeather">查询</button>
<div>
<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>
<ul>
<li v-for="item in weatherList">
{{item.type}}
<b>{{item.low}}</b>
~
<b>{{item.high}}</b>

<span>{{item.date}}</span>
</li>
</ul>
</div>


<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>

<script src="./js/vue-weather.js"></script>

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
var app=new Vue({
el:"#app",
data:{
city:"",
weatherList:[],
},
methods:{
searchWeather:function(){
// console.log('天气查询');
// 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(error){
console.log(error);
})
},
changeCity:function(city){
this.city=city;
this.searchWeather();
}
},
})

用到API:http://wthrcdn.etouch.cn/weather_mini?city= 查某地近几天天气,通过console.log(),查看返回数据,找到需要的数据

音乐播放器

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
<div id="app">
<div v-show="!isShow">
<input @keyup.enter="searchMusic" v-model="query" type="text" placeholder="输入"/>
<button @click="searchMusic">查询</button>
<ul>
<li v-for="item in musicList">
<a @click="playMusic(item.id)">+</a>
<b>{{item.name}}</b>
<span v-if="item.mvid!=0" @click="playMV(item.mvid)"><i>mv</i></span>
</li>
</ul>
<div>
<b :class="{playing:isPlaying}">播放中</b>
<img width="200" :src="musicCover"/>
</div>
<div>
<audio ref='audio' :src="musicUrl" @play="play" @pause="pause" controls autoplay loop ></audio>
</div>
<div>
<dl v-for="item in hotComments">
<dt><img width="50" :src="item.user.avatarUrl"></dt>
<dd><b>{{item.user.nickname}}</b></dd>
<dd>{{item.content}}</dd>
</dl>
</div>
</div>

<div v-if="isShow">
<video :src="mvUrl" controls="controls"></video>
<div @click="hide">hide</div>
</div>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.staticaly.com/npm/vue/dist/vue.js"></script>

<script src="./js/vue-music.js"></script>

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
var app=new Vue({
el:"#app",
data:{
// 查询关键字
query:"",
// 歌曲数据
musicList:[],
// 歌曲地址
musicUrl:"",
// 歌曲图片
musicCover:"",
// 歌曲评论
hotComments:[],
// 动画播放状态
isPlaying:false,
// 遮罩层显示状态
isShow:false,
// MV地址
mvUrl:""
},
methods:{
searchMusic:function(){
// console.log(this.query);
var that=this;
axios.get('https://autumnfish.cn/search?keywords='+this.query)
.then(function(response){
// console.log(response);
that.musicList=response.data.result.songs;
console.log(response.data.result.songs)
},function(error){
console.log(error);
})
},
playMusic:function(musicId){
// console.log(musicId);
var that=this;
// 歌曲地址
axios.get('https://autumnfish.cn/song/url?id='+musicId)
.then(function(response){
// console.log(response);
console.log(response.data.data[0].url);
that.musicUrl=response.data.data[0].url;
},function(error){
console.log(error);
})
// 歌曲图片
axios.get('https://autumnfish.cn/song/detail?ids='+musicId)
.then(function(response){
// console.log(response);
console.log(response.data.songs[0].al.picUrl);
that.musicCover=response.data.songs[0].al.picUrl;
},function(error){
console.log(error);
})
// 歌曲评论
axios.get('https://autumnfish.cn/comment/hot?type=0&id='+musicId)
.then(function(response){
// console.log(response);
console.log(response.data.hotComments);
that.hotComments=response.data.hotComments;
},function(error){
console.log(error);
})
},
play:function(){
console.log("play");
this.isPlaying=true;
},
pause:function(){
console.log("pause");
this.isPlaying=false;
},
playMV:function(mvid){
var that=this;
axios.get('https://autumnfish.cn/mv/url?id='+mvid)
.then(function(response){
// console.log(response);
console.log(response.data.data.url);
that.isShow=true;
that.mvUrl=response.data.data.url;
},function(error){
console.log(error);
})
},
hide:function(){
this.isShow=false;
}
}
})

用到API:

  • https://autumnfish.cn/search?keywords= 根据关键词查询
  • https://autumnfish.cn/song/url?id= 根据歌曲id查询具体歌曲Url
  • https://autumnfish.cn/song/detail?ids= 根据歌曲id查询具体歌曲信息
  • https://autumnfish.cn/comment/hot?type=0&id= 根据歌曲id查询具体歌曲热门评论
  • https://autumnfish.cn/mv/url?id= 根据歌曲mvid查询具体歌曲mvUrl

以上皆为网易云提供的API,感觉还是很奇妙的,使用那些在线开放的API即可实现看似很复杂的东西,让我对前端的印象有点改观

源码链接

总结

学了就是为了用,目前几乎所有开源的优秀项目,总是在readme中写明自己用到了那些技术,前后端分离项目也多的很,往往都会看到自己没有学过甚至是没有了解和听说的,对于学习那些优秀项目阻碍还是很大了,终于算是入门Vue了吧,接下来可能会做一些有趣的项目。