文章目录
Vue概述
Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:数据和 DOM 已经被建立了关联,所有东西都是响应式的。
当data中msg的数据发生改变,h1标签中的数据也会响应式的进行改变
<body>
<div id="box">
<h1>{{msg}}</h1>
</div>
</body>
new Vue({
el:'#box',
data:{
msg:'Hello Vue',
}
});
声明式渲染:只需要声明在哪里需要做什么?不需要关心具体怎么实现的
命令式渲染:需要以具体代码表达在哪里做什么?它是如何实现的
在使用Vue框架时,需要在项目中引入Vue
导入文件或者通过网页链接导入
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
Vue语法
Vue实例的创建
用Vue函数创建一个Vue实例
/*el:进行渲染的元素
data:数据*/
new Vue({
el:'#box',
data:{
msg:'Hello Vue',
}
});
模板语法
<body>
<div id="box">
<!-- {{}}:模板语法,用于数据的展示 -->
<h1>{{msg}}</h1>
<!-- 模板语法可以进行一些运算 -->
<h1>{{(30+50)*10/20}}</h1>
<h1>{{5>1}}</h1>
<h1>{{1+2>0?'大于':'小于'}}</h1>
<!-- 模板语法也可以调用JS的方法和属性 -->
<h1>{{msg.length}}</h1>
<h1>{{msg.startsWith('a')}}</h1>
</div>
</body>
new Vue({
el:'#box',
data:{
msg:'abc'
}
});
将数据显示到页面上
<body>
<div id="box">
<!-- 通过{{}}显示数据 -->
<h1>{{msg1}}</h1>
<!-- v-text:设置元素文本内容,相当于{{文本内容}} -->
<h1 v-text="msg2"></h1>
<!-- v-html:设置元素html内容 -->
<h1 v-html="msg3"></h1>
</div>
</body>
new Vue({
el:'#box',
data:{
msg1:'Hello Vue1',
msg2:'Hello Vue2',
msg3:'<s>Hello Vue3</s>'
}
});
绑定事件
<body>
<div id="box">
<!-- v-on:给元素绑定事件 -->
<button type="button" v-on:click="show1()">按钮1</button>
<!-- 事件绑定的简写方式 -->
<button type="button" @click="show2()">按钮2</button>
</div>
</body>
new Vue({
el:'#box',
data:{},
// methods:存放事件的处理函数
methods:{
// 函数可传入参数event事件对象,并使用其属性和方法
// 调用preventDefault()方法阻止事件默认行为
// 调用stopPropagation()方法组织事件冒泡行为
show1:function(){
alert("abc");
},
show2:function(){
alert("123");
}
}
})
Vue中阻止事件默认行为和冒泡行为的特有方式
<body>
<div id="box">
<div id="div1" @click="show1()" style="height:100px;width: 100px;background: red;">
<!-- 阻止事件冒泡行为 -->
<div id="div2" @click.stop="show2()" style="height:50px;width:50px;background:yellow;">
</div>
</div>
<!-- 阻止事件默认行为 -->
<a href="https://www.baidu.com" @click.prevent="show1()"></a>
</div>
</body>
new Vue({
el:'#box',
data:{},
methods:{
show1:function(){
alert("aaa");
},
show2:function(){
alert("bbb");
}
}
})
绑定属性
<body>
<div id="box">
<!-- v-bind:用于绑定data中的属性数据-->
<img v-bind:src="imgurl">
<a v-bind:href="hrefurl">百度</a>
<!-- 简写 -->
<a :href="hrefurl">百度</a>
</div>
</body>
new Vue({
el:'#box',
data:{
imgurl:"img/picture.png",
hrefurl:"https://www.baidu.com"
}
});
修改绑定的数据
切换图片
<div id="box">
<img :src="imgurl1" >
<button type="button" @click="change()">切换图片</button>
</div>
new Vue({
el:'#box',
data:{
//imgurl1:'img/picture1.png'
imgurl1:'img/ali.png'
},
methods:{
change:function(){
// this代表创建出的Vue实例
// 通过修改imgurl1数据来改变图片
this.imgurl1="img/baidu.png"
}
}
})
表单绑定
<body>
<div id="box">
<!-- v-model:绑定表单数据 -->
<input type="text" id="text1" v-model="msg"/>
<input type="text" id="text2" v-model="msg"/>
</div>
</body>
new Vue({
el:'#box',
data:{
msg:'abc'
}
})
数据的双向绑定:
如果改变text1中的数据,text2中的数据也会被改变
因为text1中的数据会返回到Vue中data中,更新msg的值,所以text2中的数据也来自data中的msg,所以也会改变
收集表单中数据
<body>
<div id="box">
<!-- @submit.prevent:阻止表单默认提交的行为 -->
<form action="123.html" method="get" @submit.prevent="submitData()">
<!--required:h5提供的属性,表单必须填入值 maxlength:最大字符的长度 -->
用户名:<input type="text" name="username" required="required" placeholder="请输入用户名" maxlength="20" v-model.trim="username" /><br>
密码:<input type="password" name="password" required="required" v-model.trim="password" /><br>
性别:<input type="radio" name="gender" value="1" v-model="gender" /> 男
<input type="radio" name="gender" value="0" v-model="gender" /> 女
<br>
爱好:<input type="checkbox" name="hobby" value="run" v-model="hobby" /> 跑步
<input type="checkbox" name="hobby" value="game" v-model="hobby" /> 玩游戏
<input type="checkbox" name="hobby" value="sing" v-model="hobby" /> 唱歌
<br>
学历:
<select name="edu" v-model="edu">
<option value="1">小学</option>
<option value="2">中学</option>
<option value="3">大学</option>
</select>
<textarea rows="" cols="" v-model="desc">
</textarea>
<input type="submit" value="提交" />
</form>
</div>
</body>
new Vue({
el: '#box',
data: {
username: '',
password: '',
// 填入radio中的value值,该radio就会被默认选中
gender: '1',
// 多选框的选项以数组形式存储在data中
// 如果需要默认选中一些选项,在数组中存储选项对应的value值
hobby: [],
edu: '1',
desc: '个人描述'
},
methods: {
submitData: function() {
var jsonObj = {
'username': this.username,
'password': this.password,
'gender': this.gender,
'hobby': this.hobby,
'edu': this.edu,
'desc': this.desc
}
}
}
})
我们也可以将表单中的数据直接收集到JSON对象中
<body>
<div id="box">
<form action="123.html" method="get" @submit.prevent="submitData()">
<!-- v-model.trim:去除用户输入的首尾空白字符 -->
用户名:<input type="text" name="username" required="required" placeholder="请输入用户名" maxlength="20" v-model.trim="formData.username" /><br>
密码:<input type="password" name="password" required="required" v-model.trim="formData.password" /><br>
<input type="submit" value="提交" />
</form>
</div>
</body>
new Vue({
el:'#box',
data:{
formatData:{
username:'',
password:''
}
},
methods:{
submitData: function() {
}
}
})
对于收集来的数据我们在提交时将这些数据发送给后台,这些操作我们在submitData函数中完成,如何发送Ajax请求在之后讲解
计算属性
在computed中方法包含getter和setter两个方法
getter方法用于获取计算过后的数据
setter方法用于监听函数返回值的变化
<div id="box">
姓名:<input type="text" name="name" id="name" placeholder="请输入姓名" v-model="name"/>
年龄:<input type="text" name="age" id="age" placeholder="请输入年龄" v-model="age"/>
个人信息:<input type="text" name="msg" id="msg" v-model="msgShow"/><br>
<!-- 也可以过通过{{}}来获取msgShow函数中getter方法的返回值 -->
{{msgShow}}
</div>
new Vue({
el:'#box',
data:{
name:'',
age:''
},
computed:{
msgShow:{
// 初始化时,get函数会被调用一次
// 当name和age的数据变化时,get函数就会被调用
get:function() {
return this.name+' '+this.age;
},
set:function(newValue){
// 如果不进行处理,name和age数据的值不会改变
console.log(newValue+"set");
// 为了保证数据的统一,需要同步改变name和age的数据
var msgs=newValue.split(' ');
this.name=msgs[0];
this.age=msgs[1];
}
}
}
})
侦听器
watch:侦听属性值的变化
<body>
<div id="box">
姓名:<input type="text" name="name" id="name" placeholder="请输入姓名" v-model="name"/>
年龄:<input type="text" name="age" id="age" placeholder="请输入年龄" v-model="age"/>
个人信息:<input type="text" name="msg" id="msg" v-model="msg"/><br>
</div>
</body>
new Vue({
el:'#box',
data:{
name:'',
age:'',
msg:''
},
watch:{
// 当属性值改变时,函数执行,可以获取新值和旧值
name:function(newValue,oldValue){
this.msg=newValue+" "+this.age;
},
age:function(newValue){
this.msg=this.name+" "+this.age;
},
msg:function(newValue){
var msgs=newValue.split(' ');
this.name=msgs[0];
this.age=msgs[1];
}
}
});
绑定class选择器的样式
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
.aClass{
background: yellow;
}
.bClass{
font-size: 50px;
}
</style>
</head>
<body>
<div id="box">
<!-- 绑定选择器时使用英文单引号将选择器名称包裹起来,否则会去找Vue实例中data中的数据 -->
<!-- 绑定一个类选择器样式 -->
<h1 :class="'aClass'">标题1</h1>
<!-- 绑定多个类选择器样式,使用数组来存储选择器名称 -->
<h1 :class="['aClass','bClass']">标题2</h1>
<!-- 通过绑定data中的数据来绑定class选择器的样式,注意不需要用单引号包裹 -->
<h1 :class="[backgroundClass,fontSizeClass]">标题3</h1>
</div>
</body>
<script type="text/javascript">
new Vue({
el:'#box',
data:{
backgroundClass:'aClass',
fontSizeClass:'bClass'
}
})
</script>
</html>
绑定style属性
<body>
<div id="box">
<!-- font-size需要改写成fontSize -->
<h1 :style="{'color':'red','fontSize':'80px','fontStyle':'italic'}">标题1</h1>
<!-- 绑定Vue中的属性数据 -->
<h1 :style="{'color':a,'fontSize':b}" @click="changeStyle(flag=!flag)">标题2</h1>
<!-- 绑定一个或多个JSON对象中的属性 -->
<h1 :style="myJson2">标题3</h1>
<h1 :style="[myJson1,myJson2]">标题4</h1>
</div>
</body>
new Vue({
el:'#box',
data:{
a:'blue',
b:'50px',
myJson1:{
'color':'yellow'
},
myJson2:{
'fontSize':'120px'
}
},
methods:{
changeStyle(flag){
if(flag){
this.a='gray';
this.b='200px';
}else{
this.a='pink';
this.b='100px';
}
}
}
})
按键修饰符
<body>
<div id="box">
<!-- 可以通过按键的键码或者别名来监听该按键是否被按下 -->
<input type="text" @keypress.enter="show1()"/>
<input type="text" @keypress.97="show2()" />
</div>
</body>
new Vue({
el:'#box',
data:{
flag:true
},
methods:{
show1(){
alert("Enter键被按下了");
},
show2(){
alert("\"a\"被输入了");
}
}
})
元素的显示与隐藏
<body>
<div id="box">
<!-- v-show:底层通过display属性来操作,值为true则元素显示,值为false则元素不显示 -->
<div id="div1" v-show="isShow">
</div>
<!-- 通过show函数改变isShow的值 -->
<button type="button" @click="show()">隐藏/显示</button>
</div>
</body>
new Vue({
el:'#box',
data:{
isShow:true
},
methods:{
show(){
this.isShow=!this.isShow;
}
}
})
条件渲染
#div1{
height: 200px;
width: 200px;
background: red;
}
#div2{
height: 200px;
width: 200px;
background: yellow;
}
<body>
<div id="box">
<!-- v-if:底层通过反复删除添加元素 -->
<!-- 如果isShow为true显示div1,为false显示div2 -->
<div id="div1" v-if="isShow">
</div>
<div id="div2" v-else="">
</div>
<button type="button" @click="show()">隐藏/显示</button>
</div>
</body>
new Vue({
el:'#box',
data:{
isShow:true
},
methods:{
show(){
this.isShow=!this.isShow;
}
}
})
多重条件
<body>
<div id="box">
<!-- v-show:不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS进行切换
v-if:它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建
v-if有更高的切换开销,而v-show有更高的初始渲染开销。
因此,如果需要非常频繁地切换,则使用v-show 较好;如果在运行时条件很少改变,则使用v-if较好。-->
<input type="text" placeholder="请输入成绩" v-model="score"/>
<h1 v-if="score>=0&&score<60">不及格</h1>
<h1 v-else-if="score>=60&&score<75">及格</h1>
<h1 v-else-if="score>=75&&score<90">良好</h1>
<h1 v-else-if="score>=90&&score<100">优秀</h1>
<h1 v-else>成绩不合法</h1>
</div>
</body>
new Vue({
el:'#box',
data:{
score:0
},
})
列表渲染
<body>
<div id="box">
<ul>
<!-- 用v-for指令基于一个数组来渲染一个列表 -->
<!-- 为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一key属性 -->
<!-- 参数:item:被迭代的数组的元素
key:如果被迭代的为键值对集合,则第二个参数为当前元素的键名
index:当前元素的索引-->
<!-- 参数和key和属性key没有关系 -->
<li v-for="(ele,index) in arr" :key="index">
{{index}}:{{ele}}
</li>
</ul>
<ol>
<li v-for="(value,key,index) in myJson" :key="key">
{{key}}...{{value}}...{{index}}
</li>
</ol>
<ul>
<li v-for="(jsonObj,index) in jsonArr" :key="index">
{{jsonObj.username}}...{{jsonObj.password}}
</li>
</ul>
</div>
</body>
new Vue({
el: '#box',
data: {
arr: [10, 20, 30, 40, 50, 60],
myJson: {
'username': 'abc',
'password': '123'
},
jsonArr: [{
'username': 'aaa',
'password': '111'
},
{
'username': 'bbb',
'password': '222'
},
{
'username': 'ccc',
'password': '333'
}
]
}
})
数组更新检测
变异方法:Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
<body>
<div id="box">
<ul>
<li v-for="(jsonObj,index) in jsonArr" :key="index">
{{jsonObj.username}}...{{jsonObj.password}}
<button type="button" @click="updateData(index)">修改数据</button>
</li>
</ul>
</div>
</body>
new Vue({
el: '#box',
data: {
jsonArr: [{
'username': 'aaa',
'password': '111'
},
{
'username': 'bbb',
'password': '222'
},
{
'username': 'ccc',
'password': '333'
}
]
},
methods: {
updateData: function(index) {
var jsonObj = {
'username': 'ddd',
'password': '123'
}
this.jsonArr[index]=jsonObj;
// 如果不调用变异方法,视图数据将不会更新
this.jsonArr.reverse();
this.jsonArr.reverse();
}
}
})
过滤器
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。
格式化文字
将小写字母改为大写字母
<body>
<div id="box">
<!-- 格式:
在双花括号中:{{ message | capitalize }}
在v-bind中:<div v-bind:id="rawId | formatId"></div>
使用过滤器时传递参数:{{ message | capitalize(参数) }}
使用多个过滤器:{{ message | capitalize1 | capitalize2 }}-->
<h1>{{msg|toUpper}}</h1>
</div>
</body>
new Vue({
el:'#box',
data:{
msg:'abcde'
},
filters:{
// value(原数据)可作为参数传入函数
toUpper:function(value){
return value.toUpperCase();
}
}
});
形参默认值
// 如果调用函数时没有传入参数,参数默认值为'abc'
function(value='abc'){
}
v-clock
这个指令保持在元素上直到关联实例结束编译
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
[v-clock]{
display: none;
}
</style>
</head>
<body>
<div id="box">
<!-- 当元素未被渲染时,页面上展示的是{{msg}},不利于用户体验 -->
<!-- 当元素未被渲染时,h1的display为none,页面上就不会展示{{msg}}
而当元素被渲染后,v-clock属性会消失,使用该属性的选择器设置的样式就会失效 -->
<h1 v-clock>{{msg}}</h1>
</div>
</body>
<script type="text/javascript">
new Vue({
el:'#box',
data:{
msg:'abcde'
},
// 延迟数据的加载,用于模拟现象
beforeCreate:function(){
alert("abc");
}
})
</script>
</html>
生命周期函数
注意:在生命周期函数中,不要使用ES6的箭头函数
Vue实例的生命周期:
使用$mount(el)函数挂载元素
var vm=new Vue({
data:{
},
})
vm.$mount('#box');
案例1:
页面元素每秒在显示和隐藏间切换一次,并提供一个按钮停止切换
<body>
<div id="box">
<h1 v-show="flag">闪烁</h1>
<button type="button" @click="stop()">stop</button>
</div>
</body>
var vm=new Vue({
el:'#box',
data:{
flag:true,
timeID:0
},
methods:{
stop:function(){
// 销毁Vue对象
this.$destroy();
}
},
// 等待页面元素挂载完毕,调用mounted函数
mounted:function(){
// 不能在setInterval方法的参数函数中取flag的值,因为此时的this不代表Vue对象
var th=this; //获取Vue对象
this.timeID=window.setInterval(function(){
console.log("定时器正在运行"); //通过在控制台打印数据证明定时器在运行
th.flag=!th.flag;
},1000);
},
// Vue对象销毁之前,调用beforeDestroy函数
// 在销毁Vue对象时,需要销毁定时器,否则定时器还在继续运行
beforeDestroy:function(){
clearInterval(this.timeID);
}
});
所有生命周期函数
<body>
<div id="box">
{{msg}}
<button type="button" @click="destroyVue()">销毁</button>
<button type="button" @click="updateMsg()">更新</button>
</div>
</body>
new Vue({
el:'#box',
data:{
msg:'数据...'
},
methods:{
updateMsg:function(){
this.msg="更新后的数据...";
},
destroyVue:function(){
this.$destroy();
}
},
beforeCreate:function(){
// beforeCreate...
// 数据:undefined
// 渲染元素:undefined
console.log("beforeCreate...");
console.log("数据:"+this.msg);
console.log("渲染元素:"+this.$el);
},
created:function(){
// created...
// 数据:数据...
// 渲染元素:undefined
console.log("created...");
console.log("数据:"+this.msg);
console.log("渲染元素:"+this.$el);
},
beforeMount:function(){
// beforeMount...
// 数据:数据...
// 渲染元素:[object HTMLDivElement]
console.log("beforeMount...");
console.log("数据:"+this.msg);
console.log("渲染元素:"+this.$el);
},
mounted:function(){
// mounted...
// 数据:数据...
// 渲染元素:[object HTMLDivElement]
console.log("mounted...");
console.log("数据:"+this.msg);
console.log("渲染元素:"+this.$el);
},
beforeUpdate:function(){
// beforeUpdate...
// 数据:更新后的数据...
// 渲染元素:[object HTMLDivElement]
console.log("beforeUpdate...");
console.log("数据:"+this.msg);
console.log("渲染元素:"+this.$el);
},
updated:function(){
// updated...
// 数据:更新后的数据...
// 渲染元素:[object HTMLDivElement]
console.log("updated...");
console.log("数据:"+this.msg);
console.log("渲染元素:"+this.$el);
},
beforeDestroy:function(){
// beforeDestroy...
// 数据:更新后的数据...
// 渲染元素:[object HTMLDivElement]
console.log("beforeDestroy...");
console.log("数据:"+this.msg);
console.log("渲染元素:"+this.$el);
},
destroyed:function(){
// destroyed...
// 数据:更新后的数据...
// 渲染元素:[object HTMLDivElement]
console.log("destroyed...");
console.log("数据:"+this.msg);
console.log("渲染元素:"+this.$el);
}
});