基本使用
基本结构
v层:div部分
vm层:实例的vm对象
m层:data数据中的msg
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<script type="text/javascript" src = "./vue.js"></script>
<body>
<div id = "app">
<p>{{ msg }}</p>
</div>
</body>
<script type="text/javascript">
//1.导入vue包
//2.创建vue实例
//导入包后,浏览器的内存中,就多了vue的构造函数
var vm = new Vue({
el:'#app',//表示vue实例要控制的页面上的区域,当div标签识别为class = “app”,此处对应为'.app';
data:{//data属性中,存放的是el中要用到的数据
msg:'欢迎学习'//通过vue提供的指令,将数据渲染到页面上,不用操作dom,vue框架不提倡手动操作dom
}
})
</script>
</html>
id最好不要写在body中。
v-cloak
当由于网速等问题导致页面渲染慢时,将会导致页面中可以短暂看到插值表达式,如下:
可以通过v-cloak解决
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<style>
[v-cloak]{
display:none;
}
</style>
<body>
<div class = "app">
<p v-cloak>{{ msg }}</p>
<!-- v-cloak 能够解决 插值表达式闪烁的问题-->
<p>{{msg2}}</p>
<p v-html="msg2"></p>
</div>
</body>
<script type="text/javascript" src = "./vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
msg:'欢迎学习',
msg2:"<p>一个段落</p>"
}
})
</script>
</html>
v-text
同时也可以用v-text解决闪烁的问题,如下:
<p v-text="msg"></p>
v-text本身不会闪烁;
但v-text的使用不够灵活,他会替代标签内的内容,不如以上情况如果为
<p v-text="msg">你好</p>
最后运行的结果为:
欢迎学习
但是使用插值表达可以,如:
<p v-cloak>你好{{ msg }}</p>
最后运行的结果为:
你好欢迎学习
v-html
v-html会将内容按照html格式解析并渲染到页面中,如v-text,v-html也会覆盖标签原本的内容;
v-bind
- v-bind: 是vue中提供的用于绑定属性的指令 ,属性绑定机制
- v-bind将引号中的内容当作变量/js表达式解释
- 简写模式只留冒号:
<body>
<div class = "app">
<p>{{ msg }}</p>
<input type="button" value="按钮" title="msg">
<input type="button" value="按钮" v-bind:title="msg + 'heihei'">
<input type="button" value="按钮" :title="msg">
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
msg:'欢迎学习',
}
})
</script>
效果:
不是用v-bind,title中的内容解释为字符串msg;使用v-bind后,将msg关联到vue中的数据msg,显示为msg对应的数据“欢迎学习”;也可以再title中写符合js的表达式,将最后结果输出到了title。
v-for
v-for能够循环数组中的内容,如content in arr;表示遍历arr数组中的每一项,每一项对应的变量放在临时变量content中,也可以加入第二个临时变量i,用于存放每一项的索引。
<body>
<div class = "app">
<span>{{ arr[0] }}</span>
<span v-for="content in arr">{{content}}</span>
<p v-for="(content,i) in arr">索引:{{i}},内容:{{content}}</p>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
msg:'欢迎学习',
arr:['a','b','c','d','e','f']
}
})
</script>
效果:
v-for也可以遍历复杂数组、对象、数字:
<body>
<div class = "app">
<p v-for="(content,i) in complexArr">序号:{{i}}, 年龄:{{content.age}}, 姓名:{{content.name}}</p>
<h3 v-for="(a,b,i) in obj">值:{{a}},  键:{{b}},  索引:{{i}} </h3>
<p v-for="num in 10">循环数字:{{num}}</p>
<!-- 使用v-for迭代数字,循环从1开始 -->
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
obj:{
name:"托尼-屎大颗",
gender:"男"
},
complexArr:[
{name:"tom",age:19},
{name:"tom1",age:20},
{name:"tom2",age:21}
]
}
})
</script>
运行效果:
当vue用v-for正在更新已渲染锅的元素列表时,它默认的用“就地复用”策略,如果数据项的顺序被改变,vue将不是移动dom元素来匹配数据项的顺序,而是简单复用此处的每个元素,并且确保他在特定的索引下显示已被渲染过的每个元素。
为了给vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每一项提供一个唯一的key属性。
如以下示例:
<body>
<div class = "app">
<div>
<label>id:<input type="text" v-model="id" name=""></label>
<label>name:<input type="text" v-model="name" name=""></label>
<input type="button" value="添加" name="" @click="add">
</div>
<p v-for="item in list">
<input type="checkbox" name="">{{item.id}}----{{item.name}}
</p>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
id:'',
name:'',
list:[{
id:1,
name:"托尼-屎大颗",
gender:"男"
},{
id:2,
name:"布鲁斯-班纳",
gender:"男"
},{
id:3,
name:"娜塔莎-罗曼诺夫",
gender:"女"
}]
},
methods:{
add(){//添加方法
this.list.push({id:this.id,name:this.name});
// this.list.unshift({id:this.id,name:this.name});
}
}
})
</script>
效果:
点击添加后,能够正常显示勾选。
将以上add函数修改后
add(){//添加方法
// this.list.push({id:this.id,name:this.name});
this.list.unshift({id:this.id,name:this.name});
}
运行效果:
勾选项由3变成了2,整体索引的勾选依旧是第三个,但是选项不是我们想要的。
修改以下代码:
<p v-for="item in list" v-bind:key="item.id">
<input type="checkbox" name="">{{item.id}}----{{item.name}}
</p>
运行效果:
能够正常勾选。
使用v-for时应该注意:
- v-for循环的时候,key属性只能使用number或者string
- key在使用的时候,必须使用v-bind属性绑定的形式,指定key的值
- 使用v-for循环的时候,或者特殊情况中,指定唯一的字符串/数字。
v-on
vue中提供了v-on事件绑定机制,示例代码如下:
<body>
<div class = "app">
<input type="button" value="speak" name="" v-on:click="say">
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
},
methods:{
say(){
alert("hello");
}
}
})
</script>
methods属性中定义了当前vue中实例的所有的可用的方法。
vm实例中,如果想要使用data中的数据,或者methods中的方法,需要this.的方式进行访问。
v-on的简写方式为@,如以上代码可修改为:
<input type="button" value="speak" name="" @click="say">
例子1
vm实例会监听自己data中的所有数据,如果数据发生变化,就会自动把最新的数据从data中同步到页面中。
代码:
<body>
<div class = "app">
<input type="button" value="run" name="" @click="run">
<input type="button" value="stop" name="" @click="stop">
<p>{{msg}}</p>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
msg:"富强民主文明和谐自由平等公正法治爱国敬业",
intervalID:null
},
methods:{
run(){
if(this.intervalID == null){
this.intervalID = setInterval(()=>{
//不是用function(),使用箭头函数,可以保证函数外部的this与内部的this保持一致
var start = this.msg.substring(0,1);
var end = this.msg.substring(1);
this.msg = end + start;
},100);
}
},
stop(){
clearInterval(this.intervalID);
this.intervalID = null;
}
}
})
</script>
效果:
事件修饰符
点击事件默认为冒泡机制,先出发内部元素的事件,再触发外部元素的事件;
<body>
<div class = "app">
<div style="height:150px;background-color: darkcyan;" @click = "clickDiv">
<input type="button" value="click" name="" @click="click">
</div>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
},
methods:{
click(){
console.log("click");
},
clickDiv(){
console.log("clickDiv");
}
}
})
</script>
结果:
.stop
阻止冒泡事件的触发;
修改代码
<body>
<div class = "app">
<div style="height:150px;background-color: darkcyan;" @click = "clickDiv">
<input type="button" value="click" name="" @click.stop="click">
</div>
</div>
</body>
结果:
.prevent
阻止默认行为
<a href = "http:www.baidu.com" @click.prevent = "linkClick">百度</a>
运行时,将会阻止跳转到百度的页面,只执行linkClick函数。
.capture
添加事件侦听器时使用事件捕获模式;即点击事件的捕获从外层向内的顺序,与冒泡相反
代码:
<div style="height:150px;background-color: darkcyan;" @click.capture = "clickDiv">
<input type="button" value="click" name="" @click="click">
</div>
结果:
.self
阻止当前元素上的冒泡触发事件行为,后续更外层的元素事件不会阻止(stop会阻止之后所有的冒泡)。
以上div与按钮的案例,div的事件为点击按钮后冒泡触发的事件,加上.self时,则只有当只点击div时才会触发div的事件。
代码:
<div style="height:150px;background-color: darkcyan;" @click.self = "clickDiv">
<input type="button" value="click" name="" @click="click">
</div>
结果为,只有点击青色区域时,才会打印clickDiv;
.once
使用.once只触发一次事件
<a href = "http:www.baidu.com" @click.prevent.once= "linkClick">百度</a>
结果,第一次点击时,阻止了跳转,第二次将会跳转到百度
v-model
唯一实现双向数据绑定的指令。
<body>
<div class = "app">
<p>{{msg}}</p>
<input type="text" name="" v-model:value="msg">
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
msg:"欢迎学习"
},
methods:{
click(){
console.log("click");
}
}
})
</script>
效果,当input中的内容修改后,p标签内的值也会随之改变。
可通过f12查看vm内容。
v-bind只能实现数据的单向绑定,M–>V,即data中的msg到页面元素中。
注意,v-model只能用于表单元素,input(raido,text,address,email…) select checkbox textarea等。
计算器练习代码:
<body>
<div class = "app">
<input type="text" name="" v-model:value = "v1">
<select v-model="cal">
<option value = "+">+</option>
<option value = "-">-</option>
<option value = "*">*</option>
<option value = "/">/</option>
</select>
<input type="text" name="" v-model:value = "v2">
<input type="button" name="" value="=" v-on:click = "fun">
<input type="text" name="" v-model:value = "res">
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
v1:"",
v2:"",
cal:"-",
res:""
},
methods:{
fun(){
// var form = this.v1 + this.cal + this.v2;
// this.res = eval(form);
switch(this.cal){
case "+":
this.res = parseInt(this.v1) + parseInt(this.v2);break;
case "-":
this.res = parseInt(this.v1) - parseInt(this.v2);break;
case "*":
this.res = parseInt(this.v1) * parseInt(this.v2);break;
case "/":
this.res = parseInt(this.v1) / parseInt(this.v2);break;
}
console.log("hello")
}
}
})
</script>
效果:
设置样式
属性绑定
- 直接传递一个数组,clsaa需要使用v-bind进行属性绑定,class类需要放在字符串中,多个使用逗号分隔;
- 也可以在传递的数组中使用三元表达式,实现变量控制样式;也可以使用对象的方式代替三元表达式
- 直接传递对象,类名为键(类名可带引号,也可不带),控制是否显示为它的值(true | false)
<body>
<div class = "app">
<h1 class="red thin">传统方法</h1>
<h1 :class="['thin','red','active']">vue中的属性绑定</h1>
<h1 :class="['thin','red',flag?'active':'']">vue中的变量控制--三元表达式</h1>
<h1 :class="['thin','red',{'active':flag}]">vue中的变量控制--对象方式</h1>
<h1 :class="{thin:true,red:true,active:flag}">vue中的变量控制--传递对象方式</h1>
<h1 :class="classStyle">vue中的变量控制--传递vue对象方式</h1>
<input type="button" value="chg" @click = "chsty" name="">
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
flag:true,
classStyle:{thin:true,red:true,active:false}
},
methods:{
chsty(){
this.classStyle = {thin:true,red:true,active:this.flag}
}
}
})
</script>
效果:
内联样式
代码示例如下:
<body>
<div class = "app">
<!-- 当键中有横线(-),键名需要加单引号 -->
<h1 :style="{color:'red','font-weight':200}">对象方法</h1>
<h1 :style="classStyle">vue成员对象方法</h1>
<h1 :style="[classStyle,classStyle1]">vue成员对象数组方法</h1>
</div>
</body>
<script type="text/javascript">
var vm = new Vue({
el:'.app',
data:{
classStyle:{color:'red','font-weight':200},
classStyle1:{'font-style':'italic'}
}
})
</script>
效果:
v-if v-show
v-if:每次都会删除或创建元素;较高的切换性能消耗
v-show:每次不会进行dom的删除或创建操作,只是切换元素的display:none样式;有较高的初始渲染消耗。
如果元素设计频繁的切换,最好不要使用v-if,而使用v-show;如果元素可能永远不会显示出,则推荐使用v-if;
过滤器
在v-bind与插值表达式(mustache)中使用。
格式:
将data的内容传到过滤器中,处理后显示。
<h1 >{{data | 过滤器名称}}</h1>
Vue.filter('过滤器名称',function(data){
return data + "123"
})
过滤器的名称也支持传递参数。
可以进行过滤器的多个调用,第一次调用的结果会作为第二次调用的输入。
<body>
<div class = "app">
<h1 >{{msg | newFilter1("他们","你们") | newFilter2}}</h1>
</div>
</body>
<script type="text/javascript">
//定义一个全局过滤器
Vue.filter('newFilter1',function(data,param,param2){
// return data.replace('你','你们')//只能替换第一个“你”
// replace的第一个参数处理字符串,还可以使用正则
return data.replace(/你/g,param+"和"+param2)
})
Vue.filter('newFilter2',function(data){
return data + " very good";
})
var vm = new Vue({
el:'.app',
data:{
msg:"你好呀,我很好,但你不行",
}
})
</script>
结果:
私有过滤器:
var vm = new Vue({
el:'.app',
data:{
msg:"你好呀,我很好,但你不行",
},
filters:{
newFilter1:function(data,param,param2){
return data.replace(/你/g,param+"与"+param2);
}
}
})
将过滤器写到vm实例内部,此时只能此vm使用这个过滤器;
如果私有过滤器与全局过滤器冲突,会优先使用私有过滤器。
按键修饰符
如下:当回车按键抬起时绑定事件add
<input type="button" @keyup.enter="add()">
系统内置的修饰符还有:
.tab
.delete(删除和退格)
.esc
.space
.up
.down
.left
.right
自定义按键修饰符:
可通过查询js 里面的键盘事件对应的键码,绑定对应的按键操作,如通过查询得到72,对应的为h键,所以可以在按下h时调用add:
<input type="button" @keyup.72="add()">
按键码不好记忆,可如下修改f2键的抬起事件
<input type="button" @keyup.f2="add()">
<script>
Vue.config.keyCodes.f2 = 112;
</script>
自定义指令
全局指令
vue中的指令都要以"v-"开头
定义方法如下:
- 使用vue.directive定义全局指令
- 参数1:指令的名称,在定义的时候,名称不需要加v-前缀,使用的时候需要加v-
- 参数2:一个对象,有一些指令相关的钩子函数,可在特定的阶段执行相关的操作
在vue中提供的钩子函数中完成功能的实现。如获取焦点指令
Vue.directive('focus',{
//在每个函数中,第一个参数永远是el,表示绑定的元素,这个el是js原生的对象
bind:function(el){//每当指令绑定到元素上,会立即执行,且只执行一次;样式相关的操作;
//在元素刚绑定指令的时候,还没有插入到dom中,这时候调用focus没有作用,因为一个元素只有插入到dom中后才能获取焦点
},
inserted:function(el){//元素插入到dom中的时候,会执行此函数,只执行一次;行为相关的操作
el.focus();
},
updated:function(){//当vNode更新的时候,会执行此函数,可能触发多次
}
})
样式的修改可以在bind时执行,不用在渲染、加载到页面中之后再修改。
使用:
<input type="text" v-focus>
私有指令
需要写在vm实例内部,在data、methods、filters的同一级:
directives:{
'fontweight':{
bind:function(el,param){
el.style.fontWeight = param.value;
}
}
}
其中param时指令的传递参数,使用如下
<input type="text" v-fontweight="800">
当只应用在bind和update的钩子函数中时,可以使用简写模式
directives:{
//这个函数等同于写到了bind和update中
'fontsize':function(el,param){
el.style.fontSize = parseInt(param.value)+"px";
}
}
案例
- vue中使用事件绑定v-on时,指定处理函数,括号可加可不加,增加括号可以方便的为函数传入输入参数。
- 数组的some方法可以在回调函数返回true时终止循环。
- v-for可以从vue方法中拿取数据
- 字符串使用indexOf时,注意空格是包含在任意字符串中的。
案例代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<script type="text/javascript" src = "./vue.js"></script>
<link rel="stylesheet" href="./bootstrap.css">
<body>
<div class = "app">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">添加品牌</h3>
</div>
<!-- form-inline元素会在一行中 -->
<div class="panel-body form-inline">
<label>
id:<input type="text" name="" class="form-control" v-model="id">
</label>
<label>
name:<input type="text" name="" class="form-control" v-model="name" @keyup.72="add">
</label>
<input type="button" value="添加" class="btn btn-primary"name="" v-on:click="add">
<label>
搜索:<input type="text" name="" class="form-control" v-model="searchWord" v-focus v-color="'blue'" v-fontweight="800">
<!-- v-color的参数为字符串,所以不能直接写成“blue”,需要加单引号 -->
</label>
</div>
</div>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>ctime</th>
<th>operation</th>
</tr>
</thead>
<tbody>
<tr v-for="item in search(searchWord)" v-bind:key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.ctime | dateFormat}}</td>
<td><a href="" @click.prevent="del(item.id)"> 删除</a></td>
</tr>
</tbody>
</table>
<h v-fontsize="10">ok</h>
</div>
</body>
<script type="text/javascript">
Vue.filter('dateFormat',function(date){
var dt = new Date(date);
var y = dt.getFullYear();
var m = dt.getMonth() + 1;
var d = dt.getDate();
var h = dt.getHours().toString().padStart(2,'0');
var m = dt.getMinutes().toString().padStart(2,'0');
var s = dt.getSeconds().toString().padStart(2,'0');;
return `${y}-${m}-${d} ${h}:${m}:${s}`
})
//自定义全局按键修饰符
Vue.config.keyCodes.f2 = 112;
Vue.directive('focus',{
inserted:function(el){//元素插入到dom中的时候,会执行此函数,只执行一次
el.focus();
}
})
Vue.directive('color',{
bind:function(el,param){
el.style.color=param.value;
}
})
var vm = new Vue({
el:'.app',
data:{
list:[
{id:1,name:"奔驰",ctime:new Date()},
{id:2,name:"宝马",ctime:new Date()}
],
id:"",
name:"",
searchWord:""
},
methods:{
add(){
var newObj = new Object();
newObj.id = this.id;
newObj.name = this.name;
newObj.ctime = new Date();
this.list.push(newObj);
this.id = "";
this.name = "";
},
del(delID){
// for(var i=0;i<this.list.length;i++){
// if(this.list[i].id == delID){
// this.list.splice(i,1);
// }
// }
this.list.some((item,i)=>{
if(item.id = delID){
this.list.splice(i,1);
return true;
}
})
},
search(word){
// var temp = [];
// this.list.forEach(item=>{
// if(item.name.indexOf(word)!= -1){
// temp.push(item);
// }
// })
// return temp;
return this.list.filter(item=>{
if(item.name.includes(word)){
return item;
}
})
}
},
directives:{
'fontweight':{
bind:function(el,param){
el.style.fontWeight = param.value;
}
},
'fontsize':function(el,param){
el.style.fontSize = parseInt(param.value)+"px";
}
}
})
</script>
</html>
效果:
工具
为方便使用,可安装vue工具vue-devtools;
更多工具,扩展程序,开发者模式,加载已解压的扩展程序,选择编译后的文件夹。