vue入门
Vue入门
第一个程序
<!DOCTYPE html>
<html>
<head>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{message}}
{{obj.name}}
{{obj.age}}
<ul>
<li>{{arr[0]}}</li>
<li>{{arr[1]}}</li>
<li>{{arr[2]}}</li>
</ul>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data:{
message: "hello",
obj: {
name: "tom",
age: 33
},
arr: ["ele01", "ele02", "ele03"]
}
})
</script>
</html>
vue范围为el挂载点及其后代元素,支持双标签但不能挂载到 html 及 body,建议使用 div。
v-text 设置文本内容
将内容直接展示在页面上
<body>
<div id="app">
<h2 v-text="message + '!'"></h2>
<h2>部分替换:{{message + "!"}}</h2>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
message: "标签文本值"
}
})
</script>
v-html 设置标签
会将标签渲染出来
<body>
<div id="app">
<p v-html="message + '!'"></p> <!-- 显示出一个超链接标签 -->
<p>部分替换:{{message + "!"}}</p> <!-- 直接显示文本 -->
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
message: "<a href=\"\">标签文本值</a>"
}
})
v-on 绑定事件
<div id="app">
<input type="button" value="单击" v-on:click="doIt">
<input type="button" value="鼠标移入" v-on:mounseenter="doIt">
<input type="button" value="双击" v-on:dblclick="doIt">
<!-- 简便写法 -->
<input type="button" value="双击" @dblclick="doIt">
<p @click="change">{{ content }}</p>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
content: "Hello"
},
methods: {
doIt: function() {
console.log("doIt");
},
change: function() {
this.content += "!" // 使用 this.xx 访问到Vue对象中的元素
}
}
});
</script>
自定义参数,事件修饰符:
<div id="app">
<input type="button" @click="doIt('老铁', 666)" value="button"> <!--向函数传入参数,字符串与数字-->
<input type="text" @keyup.enter="sayHi"> <!--事件修饰符,只有按enter键时才触发函数-->
</div>
</body>
<script>
var app = new Vue({
el: "#app",
methods: {
doIt: function(p1, p2) {
console.log(p1 + p2);
},
sayHi: function() {
console.log("sayHi function");
}
}
});
</script>
v-show 是否展示标签
设置是否拥有display属性为none的标签,消耗较小
<body>
<div id="app">
<img v-show="isShow" src="./monkey.gif"> fasle时不显示,为true时显示
<img v-show="age >= 18" src="./monkey.gif"> age元素不到18则不显示
<button @click="change">点击切换是否显示</button>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
isShow: false,
age: 18,
},
methods: {
change: function() {
this.isShow = !this.isShow;
}
}
})
</script>
v-if 选择
操纵dom元素,将标签直接添加到文档中或从文档中删除
<body>
<div id="app">
<button @click="change">切换标签显示状态</button>
<p v-if="isShow">一个标签</p>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
isShow: false,
age: 18,
},
methods: {
change: function() {
this.isShow = !this.isShow;
}
}
})
</script>
v-bind 操纵标签属性
<div id="app">
<button @click="change">点击改变</button>
<img v-bind:src="imgSrc" :title="imgTitle">
<img :class="{active:isActive}"> 标签的active属性是否生效取决于后面的值
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
imgSrc: "./monkey.gif",
imgTitle: "monkey"
},
methods: {
change: function() {
this.imgTitle = "other";
}
}
})
</script>
v-for 循环语句
<body>
<div id="app">
<ul>
<li v-for="(item, index) in arr" v-text="index + ' : ' + item"></li>
</ul>
<ul>
<li v-for="(item, index) in objArr">{{item.name}}</li>
</ul>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
arr: [1,2,3,4,5]
}
});
</script>
v-model 双向数据绑定
获取和设置表单的值
将text类型表单中的文本与vue对象中的数据绑定,改动任意一个都会引起另一个的改变。
<body>
<div id="app">
<input type="text" v-model="message">
<br/>
{{ message }}
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
message: ""
}
});
</script>
过滤器
<body>
<div id="app">
<ul>
<li v-for="user in userList">
{{user.id}} {{user.name}}
<!-- 此处使用了过滤器 -->
{{user.gender | genderFilter}}
</li>
</ul>
</div>
</body>
<script>
Vue.filter("globalFilter", function (params) {
// 全局过滤器
})
var app = new Vue({
el: "#app",
data: {
userList: [
{ id: 1, name: "张三", gender: 1 },
{ id: 2, name: "xxx", gender: 0 },
]
},
// 过滤器
filters: {
genderFilter(val) {
if (val === 1) {
return "男";
} else {
return "女";
}
}
}
})
</script>
计算属性 和 侦听器
<body>
<div id="app">
<!-- 某些结果是基于之前数据实时计算出来的,可以利用计算属性完成 -->
<ul>
<li>西游记 价格:{{xyjPrice}}, 数量:<input type="number" v-model="xyjNum"></li>
<li>总价: {{totalPrice}}</li>
</ul>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
xyjPrice: 100,
xyjNum: 1,
xyjMaxNum: 5,
// totalPrice: 22, 在计算属性中存在所以无需重复
},
// 计算属性
computed: {
totalPrice() {
return this.xyjNum * this.xyjPrice;
}
},
// 侦听器,监听一个值的变化,从而做出相应的反应
watch: {
xyjNum(newVal, oldVal) {
if (newVal < 0) {
this.xyjNum = 0;
} else if (newVal > this.xyjMaxNum) {
this.xyjNum = this.xyjMaxNum;
}
}
}
})
</script>
axios 网络请求
axios.get(地址)
.then(
function(response){}, // 成功时的回调函数
function(err){} // 失败时的回调函数
)
axios.post(地址, {key1:value1, key2:value2})
.then(
function(response){}, // 成功时的回调函数
function(err){} // 失败时的回调函数
)
在 axios 请求函数的内部,this对象已经发生了改变,所以需要用一个其他变量保存Vue对象中的this。
<div id="app">
<input type="button" id="get" value="get" @click="getRequest">
<input type="button" id="post" value="post" @click="postRequest">
<p>{{ joke }}</p>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
joke: "笑话"
},
methods: {
getRequest: function() {
var that = this; // 保存 Vue 对象中的指针,用于在 axios 中访问
axios.get("https://autumnfish.cn/api/joke/list?num=1")
.then(function (response) {
that.joke = response.data.jokes;
console.log(response.data);
}, function (err) {
console.log(err);
}
)
},
postRequest: function() {
var that = this;
axios.post("https://autumnfish.cn/api/user/reg", {"username": "Tom"})
.then(function (response) {
console.log(response.data);
}, function (err) {
console.log(err);
}
)
}
}
});
</script>
组件化
全局组件
<body>
<div id="app">
<!-- 注意要在vue作用范围内使用组件,使用组件名的标签 -->
<counter></counter>
</div>
</body>
<script>
// 注册全局组件
Vue.component("counter",{
// 指定模板,为了复用不与具体的页面产生联系
template: `<button @click="count++">我被点击了{{count}}次</button>`,
// 通过函数的方式返回数据,保证每次返回的都是独立的值
data(){
return {
count: 0
}
}
});
var app = new Vue({
el: "#app",
})
</script>
- 组件其实也是一个 Vue 实例,因此它在定义时也会接收:data、methods、生命周期函数等
- 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有 el 属性
- 但是组件渲染需要 html 模板,所以增加了 template 属性,值就是 HTML 模板
- 全局组件定义完毕,任何 vue 实例都可以直接在 HTML 中通过组件名称来使用组件了
- data 必须是一个函数,不再是一个对象。
局部组件
<body>
<div id="app">
<component-name></component-name>
</div>
</body>
<script>
const buttonCounter = {
template: `<button @click="count++">我被点击了{{count}}次</button>`,
data(){
return {
count: 0
}
}
};
var app = new Vue({
el: "#app",
components: {
// 可省略名称,只写 buttonCounter
'component-name': buttonCounter
}
})
</script>
实例
计数器
<body>
<div id="app">
<button @click="sub">-</button>
<span>{{ num }}</span>
<button @click="add">+</button>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: { num: 0, min: 0, max: 9 },
methods: {
sub: function () {
if (this.num <= this.min) {
alert("不能小于" + this.min);
} else {
this.num--;
}
},
add: function () {
if (this.num >= this.max) {
alert("不能大于" + this.max);
}
else { this.num++; }
}
}
});
</script>
图片切换
<body>
<div id="app">
<a href="#" @click="prev" v-show="!isFirst">prev</a>
<a href="#" @click="next" v-show="!isLast">next</a>
<img :src="imgSrcArr[index]">
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data:{
imgSrcArr: ["./black.png", "./monkey.gif"],
index: 0,
isFirst: true,
isLast: false
},
methods: {
prev: function(){
this.index = (this.index - 1 + this.imgSrcArr.length) % this.imgSrcArr.length;
this.isLast = false;
if (this.index == 0) {
this.isFirst = true;
}
console.log("prev" + this.index);
},
next: function(){
this.index = (this.index + 1) % this.imgSrcArr.length;
this.isFirst = false;
if (this.index == this.imgSrcArr.length - 1) {
this.isLast = true;
}
console.log("next" + this.index);
}
}
})
</script>
记事本
<!DOCTYPE html>
<html>
<head>
<meta lang="zh-cn">
<meta charset="UTF-8">
<title></title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="message" @keyup.enter="refresh">
<div v-show="msgArr.length != 0">
count: {{ msgArr.length }}
<button @click="clear">clear</button>
</div>
<ul>
<span v-for="(item, index) in msgArr">
<li>{{ index+1 + " : " + item }}</li>
<button @click="del(index)">X</button>
</span>
</ul>
<br/>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
message: "",
msgArr: []
},
methods: {
refresh: function() {
console.log(this.message);
console.log(this.msgArr);
this.msgArr.push(this.message);
this.message = "";
},
clear: function(){
this.msgArr = [];
},
del: function(index) {
this.msgArr.splice(index, 1);
}
}
});
</script>
</html>
天气查询
<body>
<div id="app">
<input type="text" v-model="city" @keyup.enter="queryCity" value="北京">
<div>
<a href="javascript:;" @click="query('北京')">北京</a>
<a href="javascript:;" @click="query('上海')">上海</a>
<a href="javascript:;" @click="query('广州')">广州</a>
<a href="javascript:;" @click="query('深圳')">深圳</a>
</div>
<ul>
<li v-for="(item, index) in inforList">{{ item }}</li>
</ul>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
city: "",
inforList: []
},
methods: {
queryCity: function (params) {
this.query(this.city);
},
query: function (city) {
var that = this;
axios.get("http://wthrcdn.etouch.cn/weather_mini?city=" + city)
.then(function (response) {
console.log(response);
that.inforList = response.data.data.forecast;
}, function (err) {
console.log(err);
})
}
}
});
</script>
音乐播放器
使用接口:
https://neteasecloudmusicapi.vercel.app/#/
https://autumnfish.cn/search?keywords=海阔天空
https://autumnfish.cn/mv/url?id=5436067
https://autumnfish.cn/song/detail?ids=347230
<!DOCTYPE html>
<html>
<head>
<meta lang="zh-cn">
<meta charset="UTF-8">
<title></title>
<script src="./vue.js"></script>
<script src="./axios.js"></script>
</head>
<body>
<div id="app">
<input v-model="keywords" type="text" value="五月天" @keyup.enter="search"><button @click="search">搜索</button>
<audio :src="audioUrl" type="audio/mp3" controls="controls" autoplay="autoplay"></audio>
<img :src="imgSrc" alt="专辑封面" height="100px" width="100px">
<video :src="mvSrc" height="200px" width="200px" autoplay="autoplay" controls></video>
<br/>
<ul>
<li v-for="(item, index) in musicList">
<a @click="playAudio(item.id)">{{ item.name }}</a>
<button @click="playMV(item.mvid)" v-if="item.mvid!=0">MV</button>
</li>
</ul>
</div>
</body>
<script>
var app = new Vue({
el: "#app",
data: {
keywords: "",
musicList: [],
audioUrl: "",
imgSrc: "",
mvSrc: ""
},
methods: {
search: function () {
var that = this;
axios.get("https://autumnfish.cn/search?keywords=" + that.keywords)
.then(function (response) {
that.musicList = response.data.result.songs;
}).catch(function (err) {
})
},
playAudio: function (songId) {
var that = this;
axios.get("https://autumnfish.cn/song/url?id=" + songId)
.then(function (response) {
that.audioUrl = response.data.data[0].url;
}).catch(function (err) {
console.log(err);
});
axios.get("https://autumnfish.cn/song/detail?ids=" + songId)
.then(function (response) {
that.imgSrc = response.data.songs[0].al.picUrl;
}).catch(function (err) {
console.log(err);
});
},
playMV: function (mvId) {
var that = this;
axios.get("https://autumnfish.cn/mv/url?id=" + mvId)
.then(function (response) {
that.mvSrc = response.data.data.url;
}).catch(function (err) {
console.log(err);
});
}
}
});
</script>
</html>