表达式
Vue的表达式不叫表达式,叫插值,写法是
{{ 5*4 }}
或者 {{ [1.2.3].reverse().join("--") }}
单次插值:{{ *val }}
值插入后不能再改变
html 插值 : {{{ htmlStr }}}
输出 html 标记
<div id="box">
<!--插值-->
{{ 5*4 }}
{{ [1,2,3].reverse().join("-") }}
{{ 4<6 ? 4<6 : false}}
{{ msg }}
<div v-html="html">{{ html }}</div> 会正确输出Hello 中国
如果是{{ html }} 则会输出 <h1>Hello 中国</h1> 带标签的原样模板
</div>
<script src="vue2.0.js"></script>链接vue2.0
<script>
new Vue ({
//产生一个vue的实例
el : "#box", //指定挂载元素
data : { //初始化数据 data 是字面量对象
msg : "Hello Vue!!!",
html :"<h1>Hello 中国</h1>"
}
})
</script>
绑定 v-bind:attr
简写形式是 v-bind:style="styleObject"
可以简写为 :style="styleObject"
<div id="box">
<span title="这是 title">鼠标停一下</span>
<span v-bind:title="msg">鼠标停一下</span>
<span v-bind:style="styleObject" v-bind:id="a" v-bind:diy="msg">鼠标停一下</span>
{{ 5 }}
</div>
- 给span 绑定一个 title 事件,鼠标放上去就会显示 " 这是 title"
- 但改一个形式 v-bind:title="msg"
msg 是我们在 data 里面初始化的变量 ,这样,鼠标再放上去的时候 就会显示 " Hello Vue!!! " - 我们又给 span 绑定一个 style 样式 , 有两个样式,标准属性前面写上 v-bind: 就可以绑定变量了. span 就会变成红色的 30px 的文字
- 用一个变量 vm 去接收 new Vue 的实例:
- 给span 绑定一个 id 属性 a 再绑定一个 diy 属性,也是 msg ,在脚本里面,如果没有初始化 msg 会报一个错误,但可以初始化一个空.
msg:" "
然后我们去浏览器的后台去输出 vm 回车,
能 看到 $el : div #box
所以 可以通过 vm.$el 拿到#box 这个节点 vm.$el == #box
写法是vm.$el
可以console.log() 一下,就能得到 id 是 box 的 div而且还能看到很多 比如: msg : "Hello Vue!!!"
还有 styleObject : 点开就能看到 fontSize 和 color
所以 : vue 把 所有 data 的东西都挂载在 实例上了.所以可以直接在后台直接更改, 很方便
<script>
//vm 会接收所有data上的数据,vm.msg === data.msg
var vm = new Vue ({
//产生一个vue的实例
//el : "#box", //指定挂载元素
data : {
msg : "Hello Vue!!!",
a : "textId",
styleObject : {
fontSize : "30px",
color : "red",
}
}
})
// console.log(vm.$el);//拿到#box的div
vm.$mount("#box");
</script>
以上: 我们可以换一种挂载方式: vm.$mount ("#box")
mount 是挂载的意思 这样也是可以的,也能实现挂载在某个节点上
$el 用于获取 vue 所挂载的元素
而$mount 用于将 Vue 实例 挂载到指定元素
样式绑定
<style>
.a{
color: blue;
}
.b{
color: pink;
}
.c{
font-size: 50px;
}
.d{
display: none;
}
</style>
- 以下 div 绑定了两个 class 样式, 但是 a 会被 b 覆盖 ,
-
:class=[first,second]
样式也可以用数组的形式来绑定, - 在数组里面写一个三元表达式
:class="[first,isShow ? ' ' : third]"
这个
<div :class="{ a : isA,b : isB }" class="c">
div 内容
</div>
<div :class="[first,second]">
<!--绑定对象,绑定数组 class-->
div 内容2
</div>
<div :class="[first,isShow ? '' : third]">
div 内容3
</div>
<div :style="[styleObject,styleObject1]">
style 数组写法
</div>
<script>
//vm 会接收所有data上的数据,vm.msg === data.msg
// 可以通过vm.$el 拿到#box 这个节点
var vm = new Vue ({
//产生一个vue的实例
data : {
msg : "Hello Vue!!!",//务必在 data 中初始化要使用的数据,否则会抛出警告
a : "testId",
isA : true,
isB : true,
first : "a",//字符串
second : "c",//字符串
isShow : true,
third : "d",
styleObject : {
fontSize : "50px",
color : "#ccc",
fontStyle : "italic",
},
styleObject1 : {
background : "#3e3e3e",
border : "2px solid cyan",
width:"500px",
},
}
})
vm.$mount("#box");// 将 Vue 实例挂载到指定的元素
</script>
条件
v-if 条件渲染 跟angular的 ng-if 是一样的
- v-if 跟angular效果一样,从DOM树中移除
- v-else 紧邻着 v-if
- v-else-if
<div id="box">
<span v-if="isShow">加油!!站起来!!</span>
<p v-else>看不到我</p>
<span v-if="isShow">Hello Vue!!!</span>
<!--<span v-else-if="!isShow">2,1新增的</span>-->
<span v-else> no Hello Vue!!!</span>
<span v-show="isShow">v-show content</span>
</div>
以上例子:
1.第一个 span 是默认显示的,如果在浏览器的控制台,改变vm.isShow=false 这样 span 就不显示了,而与 span 相反属性的 p 标签,就会显示
- 最后一个 span 标签 v-show 是隐藏元素 为 true 就显示,为 false 就隐藏
v-if v-show 的区别
区别
- (1)手段:v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显隐;
- (2)编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
- (3)编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载); v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
- (4)性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;
- (5)使用场景:v-if适合运营条件不大可能改变;v-show适合频繁切换。
<script>
var vm = new Vue({
el : "#box",
data : {
isShow : true,
}
})
</script>
写一个条件渲染的demo
<template v-if="loginType==='username'">
/* 这是判断条件 */
<label> 用户名</label>
<input type="text" placeholder="请输入用户名">
</template>
<template v-else>
<label> 邮箱</label>
<input type="text" placeholder="请输入邮箱">
</template>
<button @click="toggle">点击切换登录方式</button>
data:{
loginType:' '
}
method:{
toggle:function(){
var a = this.loginType==="username" ? 'email' :'username';
this.loginType = a;
}
/*这个三元表达式不是很好理解,先判断 this.loginType===username
true为email fasle为username 最后赋值,把this.loginType赋值为判断过后a的结果. */
}
那么在上面的代码中切换 loginType
将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input>
不会被替换掉——仅仅是替换了它的placeholder
。
如果想这两个元素独立出来,不复用,用一个key去命名就可以解决.这样就不是简单的更改playsholder这么简单了,而是两个单独的模板
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
v-show
<template v-show="ok1">
<p> v-show用在template是没有用的,例如这个v-show = 'ok1' ok1为false ,但是页面上是可以渲染出来的.
</p>
</template>
data:{
ok1:false,
}
列表渲染
v-for
<script>
var vm = new Vue({
el : "#box",
data : {
arr :["a","b","c"],
num : 5,
obj :{
name : "zhar",
address : "北京",
age : 30,
},
arr2 : [1,2,3,3],
arr3 : [{
id : 1,
name :"zhar"
},{
id : 2,
name : "tom"
}]
}
})
</script>
以上数据: 遍历出来的方法 :以下
- Vue1.0 :$index 2.0没有$index 但是要想得到下标 ,就是 <li v-for="(x,index) in arr">{{ x }}---{{ index }}</li> 没有$ 也能得到下标
值在前,下标在后
,如果index写在前面,index 得到的就是值.所以,为了方便语义化,val写在前面,index写在后面
- 整数遍历, 想当于一个 for 循环, vue 整数遍历,比angualr 的整数遍历简单,不用初始化一个数组,只用初始化一个数字就OK
- 遍历有相同元素的数组时;vue可以直接遍历, 不用track by index 比angular 简单
- vue1.0
<li v-for="x in arr" track-by="$index">
vue2.0
<li v-for="a in arr" :key="a.id">
- 遍历数组的对象的下标,参考v-for="a in arr3" 通过绑定 :key 可以得到id,
<div id="box">
遍历数组
<ul>
<li v-for="x in arr">{{ x }}</li>
</ul>
遍历对象
<ul>
<li v-for="x in obj">{{ x }}</li>
<!--只拿到值,没有键-->
</ul>
<ul>
<li v-for="(val,key) in obj">1++{{val +"--"+ key}}</li>
值在前, 键在后
</ul>
<ul>
<li v-for="(val,key,index) in obj">{{index +"--"+ key +"--"+ val}}</li>
值,键,下标,顺序要写对,得到的对应的数据就是语义化的数据,
</ul>
<ul>
<!--整数遍历 -->
<li v-for="i in num">{{ i }}</li>
结果是1,2,3,4,5,
</ul>
<ul>
遍历有相同元素的数组时;vue可以直接遍历, 不用track by index 比angular 简单
<li v-for="a in arr2">{{ a }}</li>
</ul>
<ul>
<!--angular 中碰见相同元素的数组时,是track by $index-->
<!--vue1.0 <li v-for="x in arr" track-by="$index">-->
<!--vue2.0 <li v-for="a in arr" :key="a.id">-->
<li v-for="a in arr3">{{ a }}</li>
<li v-for="a in arr3" :key="a.id">{{ a.name}}----{{a.id }}</li>
输出结果是 zhar---1 tom---2
</ul>
</div>
v-if v-for一起使用
v-for比v-if有更高的优先级,所以如果v-if要判断的话,在v-for的外层元素上加v-if进行判断
事件
- 添加事件的方法是,
v-on:click
简写形式是@click
- 第一个 button ,点击 {{ a }} 插值就会显示 true 或者 false ,因为 a 就是脚本里面初始化的值,初始是true ,然后button 绑定的是 非a 所以点击一下,就会显示false 再点击就会显示true 默认是 true
- 第二个button 绑定的changeEvent 事件 ,是个函数,函数就不能写在data里面初始化了,要写在 methods 配置项里面去初始化,
- change 事件 可以不传参,也可以传参
先说不传参的: change 绑定的还是 插值 a 的状态 点击false 再点击就是true
------------分割线------------
再说传参的: 第一个是默认的参数,$event 打印出来的是 mouseevent 和其他的两个 a b 参数, - 又声明了一个foo函数,在页面输出的时候,一定要 是
{{ foo() }}
返回的是一个随机数, 而不能不加括号,否则输出的是function boundFn(a) { var l = arguments.length; return l ? l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) : fn.call(ctx) }
是一堆看不太懂的东西 - 下面又初始化了一个数据, firstname 和lastname 在methods里面初始了一个函数,返回的是 firstname+lastname 方法的调用就是加上括号 也能用上data 的数据
添加事件的放法就是 v-on:click 或者 @click click可以换成别的事件,mouseenter mouseleave等
- 事件冒泡 ,如果子元素和父元素绑定上相同的click事件,就会由子触发,一直触发到父,一直往外冒泡, Vue 提出的解决办法是
@click.stop
就可以阻止事件往外冒泡,
DOM 提供的方法是
event.stopPropagation() 和addEventlisten() 阻止冒泡,
jquery也提供了方法: 是
event.preventDefault()
event.stopPropagation();
- 下面代码里面的 input 绑定了 v-model 绑定的是 firstName这个变量 , 添加事件叫
@keydown
键盘按下事件,后面的都是修饰符,按上下左右键和deleta键才会在控制台输出,否则,不管页面怎么修改,控制台都不会输出
还有这么多修饰符可以添加
这个图片是键盘修饰符,还有stop,还有preevent可以连用
<div id="box">
<button v-on:click="a=!a">点击show/hide</button>
输出 v-on:click="a=!a"{{ a }}
<button type="" v-on:click="changeEvent">clicktwo</button>
<button type="" @click="changeEvent($event,'a','b')">dian ji 3</button>
<!--$event 是默认的参数,如果在事件处理中,想同时使用时间对象和其余的参数,需要显示传入$event -->
<h1 v-show="a">{{ msg }} show is show </h1>
{{ foo() }}
{{ fullName()}}
<!-- 添加事件的方式, v-on:click=" " -->
<!-- v-on:eventName="" -->
<!-- @enentName 是 v-on-eventName 的简写形式-->
修饰符
<div @click="p1">
this is div
<button @click.stop="changeEvent">click it</button>
<!--引发冒泡-->
<!-- 修饰符: v-on:eventName.modifier.stop 阻止冒泡 -->
<input type="text" v-model="firstName" @keydown.left.right.up.down.delete="p2">
<!--跟一个 .left -->
{{ firstName }}
</div>
</div>
<script>
var vm = new Vue({
el : "#box",
data : {
msg : "HELLO VUE!!!",
a : true,
firstName : "tom",
lastName : "--merry",
},
//创建方法,
methods : {
//新的配置项 添加新的方法 都放在methods 里面
changeEvent : function(e,d,f){
//this 指向的是vm实例
this.a = !this.a;
console.log(e,d,f);
},
foo : function(){
return Math.random();
},
fullName : function(){
return this.firstName+this.lastName ;
},
p1 : function(){
console.log("div click event")
},
p2 : function(){
console.log(this.firstName)
}
}
})
</script>
model
v-model 就是将我们的数据和表单数据进行绑定
- c2 初始化是一个数组,给三个不同的checkbox 不同的 val , 如果 checkbox 是true ,他的 value 的值,就会被添加到 c2 数组,如果是 false , val 就会从数组里删除
- v-model 还有单选还有下拉列表,自己看手册练一练
- 最后一个input 绑定的事件有点多,可以单独去练一练 但这里有一个知识点,就是
true-value="hello" false-value="bye"
这是绑定的字符串,点击就是hello,再点击就是bye , 但是如果想绑定变量,就要用v-bind:true-value="a" v-bind:false-value="b"
虽然看上去效果差不多,但是 一个是固定的字符串,一个是变量
我刚才试了一下,c3 如果是字符串的话,变量a 和变量b 的形式都得是字符串,
如果形式不一样,就会得不到正确的输出
<div id="box">
<input type="text" v-model="msg">
<h1>{{ msg }}</h1>
<input type="checkbox" v-model="c1">
<h1>{{ c1 }}</h1>
<input type="checkbox" v-model="c2" name="" value="a">
<input type="checkbox" v-model="c2" name="" value="b">
<input type="checkbox" v-model="c2" name="" value="c">
<h1>{{ c2 }}</h1>
<!--显示在页面上的是 input 的 value -->
<input type="checkbox" v-model="c3" name=""
true-value="hello" false-value="bye"
v-bind:true-value="a" v-bind:false-value="b"
>
<h1>{{ c3 }}</h1>
</div>
</body>
<script src="vue2.0.js"></script>
<script>
var vm = new Vue({
el : "#box",
data : {
msg : "hello china",
c1 : true,
c2 : ["tom"],
//数组,绑定空数组,把你选中的 value 放进数组 ,默认有一个 tom ,就会向后追加
c3 : "",//初始化 c3 是字符串,
a : "我是真的",
b : "我是假的",
},
})
</script>
计算属性
{{ computedFullName() }}
这个方法是添加在 methods 里面的,没毛病啊,之前说过的,方法是添加在 methods 里面的
- 但是 vue 提供了更加便利的配置项, computed ,所以那个依赖 data 的 函数,可以写在 computed 这个配置项里面,data 里面的 fullname 就没有必要了,因为他是计算出来的,再计算属性里面 把 fullname 写成一个函数,返回的是firsname + lastname 可以直接在body 里面用插值输出fullname
- 用methods 也可是实现fullname 但为什么还存在计算属性
他们之间的差别是:
A: 计算属性是缓存的,只有依赖的值发生变化时,他才会发生变化,
给一个 button 点击事件, 输出 this,fullname 输出的是同一个值
如果写在methods 里面,每执行一次,会被重新调用一次,多使用计算属性,
<div id="box">
{{ firstName+lastName }}
{{ computedFullName() }}
{{ fullName }}
{{ fullName }}
<button type="" @click="clickEvent">click it</button>
{{ str }}
<span v-html="str"></span>
</div>
</body>
<script src="vue2.0.js"></script>
<script>
var vm = new Vue({
el : "#box",
data : {
activeIndex : 0,//设置默认激活的面板
msg : "hello china",
firstName : "zhar",
lastName : "tom",
str : "<h1>this is HTMLstr</h1>",
// fullName : "",
},
computed :{
//计算属性 多使用计算属性,计算购物车 依赖单价和数量,声明多个
//watch 的属性监听 事件
fullName : function(){
return this.firstName+this.lastName+new Date().getTime();
},
},
//创建方法,
methods : {
// computedFullName : function(){
// return this.fullName=this.firstName+this.lastName
// },
clickEvent : function(){
console.log(this.fullName);
},
}
})
</script>
补充一点,上面提到过的,初始化一个模板字符串,直接用插值输出的话,输出的是模板字符串原样,如果用<span v-html="str"></span>
输出的就是正确的被渲染过的标签内容
fullName:{
get: function(){
return this.firstName +' '+ this.lastName;
},// 只写get方法的话,是单向数据绑定,fullName的改变依赖于firstName或者lastName.
set: function (newValue){
var names = newValue.split(' ');
console.log(22,names)
this.firstName = names[0];
this.lastName = names[names.length - 1];
} // 加上set方法的话,就是双向数据绑定,fullName改变,firstName和lastName也会改变
}
- 以上
fullName
方法写在computed计算属性里面,是通过计算得到的
- 以上
class 与 style 绑定
绑定HTML class
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
data: {
isActive: true,
hasError: false
}
对象语法
- 绑定一个属性,
<div v-bind:class="active"></div>
- 绑定多个属性
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
括号里面用逗号隔开 - 绑定2个或者3个以上的属性
<div v-bind:class="classObject"></div>
data:{
classObject:{
info : false,
info2 : true,
info3: true,
info4: false
}
}
- 还有就是通过计算属性添加类(以后项目中会使用)
<div v-bind:class="classObject"></div>
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
这是绑定多个属性的进阶版.
数组语法
- 普通的数组语法
<p :class="[activeClass,errorClass]">{{ msg }}</p>
data:{
activeClass: 'info',
errorClass: 'info3',
}
最后的渲染结果就是两个类都添加上了.
- 三元表达式的数组语法
<p :class="[ isactive ? activeClass : errorClass ]">{{ now }}</p>
<hr>
<button @click="click">点击添加属性</button>
data:{
isactive:false
}
methods:{
click:function(){
this.isactive = !isactive;
}
}
最后实现的效果就是点击按钮可以切换两个属性
不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
用在组件上
跟用在html标签上的用法一致, 可以用三元表达式,数组语法,对象语法
绑定内联样式
- 内联跟class样式差不多,也有对象语法,数组语法,不一样的是,内联样式,是写在style="{ }" 这个大括号里面的
对象语法
<div :style="{ color: 'red', background: 'cyan',fontSize: num+'px'}">这是style绑定的对象语法</div>
data:{
num: 30,
}
也可以不直接写样式,变成动态的,可变的
<div :style="styleObj">你好啊反馈的积分卡蓝灯就估计得发老公觉得</div>
- 直接绑定到一个样式对象通常更好,这会让模板更清晰,同样的,对象语法常常结合返回对象的计算属性使用。以下:
data:{
styleObj:{
color:'#333',
background:"#f0f0f0",
fontSize: '24px'
},
}
数组语法
可以把多个 样式对象 应用到同一个元素中
<div v-bind:style="[baseStyles, overridingStyles]"></div>
data:{
baseStyles:{
width:'200px',
height:'100px',
background:'cyan',
},
overridingStyles:{
color:'red',
fontSize:'30px'
}
}
自动添加前缀
当 v-bind:style
使用需要添加浏览器引擎前缀的 CSS 属性时,如 transform
,Vue.js 会自动侦测并添加相应的前缀。