vue学习
vue大致模板:
- 引入链接:vue.js,提取码:uvrq
- 实例化vue对象
- 定义数据对象属性
- 定义函数
例如
<head>
<script src="lib/vue.min.js"></script>
<!--
第一步:引入vue
第二步:实例化vue对象
el参数是DOM元素中的id,意味操作在指定id的元素内起作用,外部不受影响
data参数用于定义数据对象属性
methods参数用于定义函数,可以通过 return来返回函数值
{{}} 用于输出对象属性和函数返回值。
-->
</head>
<body>
<div id="a">
{{one}}
<p>
{{two}}
</p>
{{sum(one,two)}}
</div>
<script>
new Vue({
el:'#a',
data:{one:1,two:2},
methods:{
sum:function(a,b){
return '总和是'+(a+b);
}
}
})
</script>
</body>
说明实例化vue对象时el参数指定的作用就是javascript中的document.getElementById(‘id’)
数据绑定
mustache表达式
- 最常见的形式就是使用 {{}}(双大括号)的文本插值,因为{{}}像胡子的样子,称之为胡须表达式
<div id="a">
{{message}}
</div>
<script>
new Vue({
el:'#a',
data:{message:'小红'}
})
</script>
v-html指令
- 使用v-html指令用于输出html代码
<div id="app">
<div v-html="message"></div>
</div>
<script>
new Vue({
el:'#app',
data: {message:'<h1>菜鸟教程</h1>'}
})
</script>
v-model指令的双向绑定
- 使用v-model指令用于双向绑定
v-model 指令用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。
<div id="app">
<input type="checkbox" v-model="flag">
<input type="text" v-model="flag">
<br>
{{flag}}
</div>
<script>
new Vue({
el: '#app',
data:{
flag: ''
}
});
</script>
现在在data里flag的数据为空,选中复选框就相当于在写入flag为true的数据,取消复选框就相当于写入flag为false的数据。可看到选中复选框实在写入value为true,而输入value会改变checked属性,所以会选中。当v-model对应"字符串"时会解析"字符串"为布尔值,v-model对应有值或是true,checkbox都会选中。
用户输入:
在input 输入框中我们也可以使用 v-model 指令来实现双向数据绑定
<body>
<div id="app">
<span>{{ message }}</span>
<br>
<input v-model="message" placeholder="你输入什么我就显示什么">
</div>
<script>
new Vue({
el: '#app',
data: {
message: ''
}
})
</script>
</body>
v-bind指令的标签属性
- 使用v-bind指令用于改变标签属性中的值
对标签class属性的绑定:
<style>
.c{
background: #444;
color: #eee;
}
</style>
<body>
<div id="app">
<input type="checkbox" v-model="flag">
<span v-bind:class="{'c': flag}">
是否使用c样式:{{flag}}
</span>
</div>
<script>
new Vue({
el: '#app',
data:{
flag: false
}
});
</script>
</body>
在了解了复选框的原理后,选中复选框,值变为true,然后span元素绑定的class属性也就变为c,取消复选框,值变为false,然后span元素绑定的class属性也就变为空。
(v-bind:class可以缩写为:class,如 <span :class="{‘c’: flag}">)
对标签的局部style绑定:
<body>
<div id="app">
<p :style="{fontSize:'50px',color:'red'}">{{name}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
name:'小汉'
}
})
</script>
</body>
<body>
<div id="app">
<p :style="{fontSize:fontSize+'px',color:color}">{{name}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
name:'小汉',
fontSize:100,
color:'blue'
}
})
</script>
</body>
对标签src属性绑定:
<body>
<div id="app">
<img :src='url'/>
</div>
<script>
new Vue({
el: '#app',
data: {
url: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=408181915,422730858&fm=26&gp=0.jpg'
}
})
</script>
</body>
对标签href绑定:
<body>
<div id="app">
<a :href="url" target="_Blank">
点击查看
</a>
</div>
<script>
new Vue({
el: '#app',
data: {
url: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=408181915,422730858&fm=26&gp=0.jpg'
}
})
</script>
</body>
支持javascript表达式
- 支持javascript表达式
<style>
#list-1{background: black;color: red;}
</style>
</head>
<body>
<div id="app">
{{5+5}}<br>
{{ ok ? 'YES' : 'NO' }}<br>
{{ message.split('').reverse().join('') }}<br>
<span v-bind:id="'list-' + id">菜鸟教程</span>
</div>
<script>
new Vue({
el: '#app',
data: {
ok: true,
message: 'RUNOOB',
id : '1'
}
})
</script>
</body>
指令
指令是带有 v- 前缀的特殊属性。用于在表达式的值改变时,将某些行为应用到 DOM 上。
v-if 条件语句
- vue中条件语句的用法,类似于java中的if-else-else_if的用法,加上v-即可。
- v-if 指令将根据表达式的值(true 或 false )判断,如果有v-else 、v-else-if 必须跟在 v-if 或者 v-else-if之后。
<div id="app">
<button @click="show=!show">点击切换</button>
<br>
<span v-if="show">显示1</span>
<span v-show="show">显示2</span>
</div>
<script>
const app=new Vue({
el:"#app",
data:{
show:true
}
});
</script>
v-show 指令
v-show根据条件来展示元素。
和v-if有点类似,但还是有很大的区别:
v-if如果条件为false,那么在生成的HTML语句中,条件为false的标签不会生成在代码中;而v-show不管条件为true还是false都会生成条件对应true和false的代码。
总的一点:v-if当在执行后会删除条件为false的标签代码,v-show在执行后只是在条件为false的标签代码上加上"display:none"的css样式使其隐藏。
v-cloak 指令
html页面是从上向下执行解析的,v-cloak用来解决有时候mustache表达式还没有被解析到而显示{{数据}}的时候过几秒才解析到显示数据的情况。
现在模拟下页面延迟解析script的vue对象使mustache表达式开始时是纯文本:
<body>
<div id="app">
<p>{{ message }}</p>
</div>
<script>
setTimeout(function(){
new Vue({
el: '#app',
data: {
message: '小汉'
}
});
},2000);
</script>
</body>
现在给p对象加上v-cloak命令:
<head>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<style>
[v-cloak] {display: none; }
</style>
</head>
<body>
<div id="app">
<p v-cloak>{{ message }}</p>
</div>
<script>
setTimeout(function(){
new Vue({
el: '#app',
data: {
message: '小汉'
}
});
},2000);
</script>
</body>
可以看到在v-cloak命令加上后没有解析到的时候就是隐藏的状态,当解析到了后就会把标签的display:none的属性自动删去然后显示出来。
v-for循环语句
数组元素循环
<body>
<div id="app">
<span v-for="i in students">
{{i.name}} : {{i.age}}
<br>
</span>
</div>
<script>
var app=new Vue({
el:'#app',
data:{
students:[
{name:'张三',age:12},
{name:'李四',age:16},
{name:'王五',age:18},
{name:'赵六',age:10}
]
}
})
</script>
</body>
对象属性循环
- 一个参数:
<body>
<div id="app">
<span v-for="i in student">
{{i}}
<br>
</span>
</div>
<script>
var app=new Vue({
el:'#app',
data:{
student:{
name:'张三',
age:18,
sex:'男'
}
}
})
</script>
</body>
- 两个参数:
<body>
<div id="app">
<span v-for="(value,key) in student">
{{key}}:{{value}}
<br>
</span>
</div>
<script>
var app=new Vue({
el:'#app',
data:{
student:{
name:'张三',
age:18,
sex:'男'
}
}
})
</script>
</body>
- 三个参数
<body>
<div id="app">
<span v-for="(value,key,index) in student">
{{index}} - {{key}} - {{value}}
<br>
</span>
</div>
<script>
var app=new Vue({
el:'#app',
data:{
student:{
name:'张三',
age:18,
sex:'男'
}
}
})
</script>
</body>
v-on触发事件
完整语法:v-on:click="doSomething"
缩写:@click="doSomething"
<body>
<div id="app">
<input type="text" v-model="n"/>
<button type="button" @click="incre">点击++</button>
<!-- @click和v-on:click都是一样的 -->
</div>
<script>
const app=new Vue({
el:"#app",
data:{
n:0
},
methods:{//固定,里面写需要用的所有的方法
incre(){//自定义的点击方法
this.n++//this,表示#app对象里的n
}
}
});
</script>
</body>
事件修饰符
vue.js为v-on提供了事件修饰符,修饰符是由点开头的指令后缀来表示:
.self:只有元素自身触发事件才执行。冒泡和捕获不执行
.once:只执行一次
.stop:阻止事件冒泡到父元素
.prevent:阻止默认事件发生
.capture:使用事件捕获模式
-
右键阻止默认事件
-
常规方式:
v-on:contextmenu.prevent="func"
简化方式:
@contextmenu.prevent="func"
按键修饰符
在监听键盘事件时,vue为v-on监听键盘事件时添加按键修饰符
全部的按键别名:
.esc
.space
.up
.down
.left
.right
.enter
.tab
.delete
常规方式:<input v-on:keyup.enter=“func”>
简化方式:<input @keyup.enter=“func”>
<body>
<div id="app">
<input id='ins' type="text" v-on:keyup.enter="func"/>
{{n}}
</div>
<script>
const app=new Vue({
el:"#app",
data:{
n:''
},
methods:{
func(){
this.n=document.getElementById('ins').value;
alert(document.getElementById('ins').value);
}
}
});
</script>
</body>
过滤器
用作一些常见的文本格式化,由"管道符"指示。
<!-- 在两个大括号中 -->
{{ message | capitalize }}
<!-- 在 v-bind 指令中 -->
<div v-bind:id="rawId | formatId"></div>
去除输入内容的空格:
<body>
<div id="app">
{{ message | formatMethod }}
<br>
<input type="text" v-model="message" />
</div>
<script>
new Vue({
el: '#app',
data: {
message: ''
},
filters: {
formatMethod: function (x) {
for(var i in x)
x=x.replace(' ','');
return x
}
}
})
</script>
</body>
过滤器也可以关联(例如下面这个一起过滤掉输入内容的空格和敏感字符):
<body>
<div id="app">
{{ message | formatMethod |formatX1}}
<br>
<input type="text" v-model="message" />
</div>
<script>
new Vue({
el: '#app',
data: {
message: ''
},
filters: {
formatMethod: function (x) {
for(var i in x)
x=x.replace(' ','');
return x
},
formatX1: function(x){
for(var i in x)
x=x.replace('操','*').replace('草','*').replace('艹','*');
return x
}
}
})
</script>
</body>
computed计算属性
计算属性关键词: computed
计算属性在处理一些复杂逻辑时是很有用的
计算属性里的对象一般有get set属性,但是一般不对set属性设置(只读对象),完整写法如下:
<body>
<div id="app">
{{full}}
</div>
<script>
new Vue({
el: '#app',
data: {
a:'小',
b:'汉'
},
computed:{
full:{
set:function(){
},
get:function(){
return this.a+this.b;
}
}
}
})
</script>
</body>
由于大部分都是只读,所以对象可以直接写为下面这种,只写出get的操作代码:
<body>
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: '123456'
},
computed: {
reversedMessage: function () {
// this指向这个匿名vue对象本身
return this.message.split('').reverse().join('')
}
}
})
</script>
</body>
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。使用 computed 性能会更好,但是如果不希望缓存,可以使用 methods 属性。(methods属性没有缓存,computed属性有缓存)
计算属性既然是属性所以在计算属性里定义的东西都是可以当数据来用的直接写{{XXX}}不需要写{{XXX()}}
区别演示:(但是有一点,计算属性的名称不要和方法名称一样了,不然会报错识别不出来)
<div id="app">
<p>{{getfull()}}</p>
<b>{{full}}</b>
</div>
<script>
new Vue({
el: '#app',
data: {
name:'小汉',
color:'blue'
},
methods:{
getfull(){
return this.name+" "+this.color;
}
},
computed:{
full:function (){
return this.name+' '+this.color;
}
}
})
</script>
watch监听属性
响应数据的变化
- 常用用法
new Vue({
el: '#app',
data: {
a: ''
},
watch: {
a(newVal,oldVal) {
// 监听响应的处理
}
}
})
如下面这个例子:
<body>
<div id = "app">
<p>计数器: {{ counter }}</p>
<button @click = "counter++">点我</button>
<br>
{{rs}}
</div>
<script type = "text/javascript">
new Vue({
el: '#app',
data: {
counter: 0,
rs:''
},
watch: {
counter(newVal, oldVal) {
this.rs='counter由' + oldVal + '变为' + newVal;
}
}
})
</script>
</body>
这种常用用法watch有一个特点,就是当值第一次绑定的时候,不会执行监听函数,只有值发生改变才会执行。
- 立即执行(immediate和handler)
监听的数据后面写成json对象形式,包含handler方法和immediate,上面写的常用用法写的函数其实就是在写这个handler方法
new Vue({
el: '#app',
data: {
a: ''
},
watch: {
a: {
handler(newVal,oldVal) {
// 监听响应的处理
},
immediate: true
}
}
})
如下面这个例子:
<body>
<div id = "app">
<p>计数器: {{ counter }}</p>
<button @click = "counter++">点我</button>
<br>
{{rs}}
</div>
<script type = "text/javascript">
new Vue({
el: '#app',
data: {
counter: 0,
rs:''
},
watch: {
counter:{
handler(newVal, oldVal) {
this.rs='counter由' + oldVal + '变为' + newVal;
},
immediate:true
}
}
})
</script>
</body>
immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。
- 深度监听
当需要监听复杂数据类型(对象)的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
设置deep: true 则可以监听到对象.属性的变化,此时会给对象的所有属性都加上这个监听器,当对象属性较多时,每个属性值的变化都会执行handler。
使用字符串的形式监听对象属性
new Vue({
el: '#app',
data: {
person: {name:'小汉',age:18,sex:'男'},
rs:''
},
watch: {
'person.age':{
handler(newVal, oldVal) {
// 监听响应的处理
},
deep:true,
immediate:true
}
}
})
如下面这个例子:
<body>
<div id = "app">
<p>{{person.name}}的年纪: {{ person.age }}</p>
<input type='text' v-model='person.name' />
<br>
<button @click = "person.age++">年纪+1</button>
<br>
{{rs}}
</div>
<script type = "text/javascript">
new Vue({
el: '#app',
data: {
person: {name:'小汉',age:18,sex:'男'},
rs:''
},
watch: {
'person.age':{
handler(newVal, oldVal) {
this.rs=this.person.name+'的年纪由' + oldVal + '变为' + newVal;
},
deep:true,
immediate:true
}
}
})
</script>
</body>
数组(一维、多维)的变化不需要通过深度监听,对象数组中对象的属性变化则需要deep深度监听。