Vue基础(2)
上次说到了vue的一些基本语法,包括数据的单向/双向绑定,这次针对样式的绑定、内置指令、事件相关问题已经自动收集表单数据做一些总结;
1. 样式绑定
我们在搭建页面时,一个常见的需求就是给页面元素添加样式,常用的两种方式就是使用类的绑定和style内联样式绑定。在vue中,我们也将针对这两种绑定方式来聊聊在vue项目中如何给元素添加样式。
- 类的绑定
<style>
.classA{
background-color:skyblue
}
.classB{
font-size:50px
}
.classC{
font-weight:700
}
</style>
<div id="root">
<!-- 1. 由传入的数据决定,你也不知道是哪个类生效 -->
<p :class="myClass">我是一个p标签</p>
<!-- 2. 知道有哪几个类,但是不知道哪个生效-->
<!-- 以对象的形式出现,属性名后的属性值是布尔值,为true就生效 -->
<p :class="{classA:isA, classB:isB}">我是一个p标签</p>
<!-- 3. 多个类都生效,以数组的形式将几个类展示出来 -->
<p :class="['classA','classB','classC']">我是一个p标签</p>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
myClass:"classA",
isA:false,
isB:true
}
})
</script>
- style的绑定
<div id="root">
<!-- style的绑定,引号中间使用对象写法,属性名改成小驼峰-->
<p :style="{fontSize:mySize,color:myColor}">我是一个p标签</p>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
myColor:"red",
mySize:"80px"
}
})
</script>
注意:
由上面两个示例可以看出,当模板中的数据一旦使用动态数据绑定的,那么属性后面的" "
就不再是字符串标识了,而是js的代码区域。
2. 内置指令
之前在介绍数据绑定时,有使用过三个内置指令v-bind、v-model和v-on
这里再介绍几个有关条件渲染和列表渲染的指令
1)条件渲染
v-if / v-else & v-show 指令
<div id="root">
<p v-if="isOk">成功</p>
<p v-else>失败</p>
<br />
<p v-show="isOk">success</p>
<p v-show="!isOk">fail</p>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
isOk:true
}
})
</script>
上面的例子输出之后,可以看到,两个指令都可以根据data
中的数据,渲染出符合条件的内容。但是,这两种方式还是有一定区别的。
在控制台中,我们发现:
使用v-if的元素会将符合条件的元素添加到DOM树中,并将其渲染到页面上;而使用v-show的元素,不管是否符合条件,在DOM树上都可以看到,只不过对于不符合条件的元素,将其隐藏掉了。
那么问题来了,在这两种指令的选择上,究竟该如何选择呢?
小结:
这两种都可以完成条件渲染的功能,但是场合不同,使用这两种的效率不一样,
当我们切换的频率很高,就选择使用v-show;切换不频繁的情况,就使用v-if/v-else;
-
使用v-if时,符合条件的才渲染,不符合条件的DOM节点就直接删除掉,内存中也不存在。(节省内存)
-
但是使用v-show,所有DOM节点都存在在DOM树上,只有符合条件的才显示,不符合条件的仅仅是使用样式隐藏起来,也就是说内存当中还有。
-
使用v-if的时候,DOM节点不一定能获取到;但是使用v-show时,DOM节点一定能获取到,只不过获取到的节点可能样式是
display:none
罢了。
2)列表渲染
v-for指令
<div id="root">
<ul>
<!-- 使用v-for指令时,必须要添加一个key属性,用来唯一指定每个渲染出来的li -->
<li v-for="(item,index) in persons" :key="item.id">
{{item.name}} --- {{item.age}}
</li>
</ul>
<!-- 添加一个修改li内容的click方法 -->
<button @click="changeLi">修改第一个li中的name值</button>
</div>
<script>
let vm = new Vue({
el:"#root",
data:{
persons:[
{id:1,name:"tony",age:25},
{id:2,name:"tom",age:15},
{id:3,name:"jenna",age:29},
{id:4,name:"lucas",age:32},
]
},
methods:{
changeLi(){
// 第一种方法:
this.persons[0].name = "Andy";
// 第二种方法:
this.persons.splice(0,1,{id:1,name:"Andy",age:25})
// 第三种方法:不可行
this.persons[0] = {id:1,name:"Andy",age:25}
}
}
})
</script>
这里引出一个很重要的问题:vue是如何处理响应式数据的?
vue在处理对象和数组时是不同的:
- 对于对象来说,data当中所有的属性,都被添加了getter和setter方法,因此data中的数据都是响应式的,修改数据,页面也会跟着改变。
- 但是,对于数组来说,数组的下标不属于属性,因此没有添加getter和setter方法,它们不是响应式的。通过数组下标(示例中的第三种方法)去修改数据,数据会改变,但是页面不会跟着改变。
- vue在对数组进行响应式的时候,不像对象一样,直接给属性添加getter和setter方法,而是重写了数组部分的方法,在原来原生方法的基础上添加了修改页面的功能。
3. 事件相关
- 事件对象event的问题
当我们给某个元素添加了事件是,不传参数时,事件处理函数内部自动传入一个event事件对象。
<div id="root">
<button @click="test">test按钮</button>
</div>
<script>
let vm = new Vue({
methods:{
test(event){
console.log(event)
}
}
})
</script>
一旦你传递了参数,那么这个参数就会将event事件对象覆盖,我们就没办法打印得到事件对象了。这时,就要用到$event
来获取事件对象
<div id="root">
<!-- 如果还想要事件对象,那么参数就使用$event,就可以接收到event对象了,顺序无所谓 -->
<button @click="test("zs",$event)">test按钮</button>
</div>
<script>
let vm = new Vue({
methods:{
test(name,event){
console.log(name,event)
}
}
})
</script>
- 阻止事件冒泡 & 取消浏览器的默认行为
在原生的js中,我们通常使用event.stopPropagation()
和event.preventDefault()
来实现阻止事件冒泡和取消浏览器的默认行为。但是,vue使用了一种更为简单的方式实现这一需要。
<div @click="outer">
<!-- 使用事件描述符 -->
<div @click.stop = "inner"></div>
<!-- 阻止浏览器的默认行为,使用事件描述符 -->
<a href="www.baidu.com" @click.prevent="cancelDef">点我跳转</a>
</div>
<script>
methods:{
outer(){
console.log("这是outer")
},
inner(event){
// event.stopPropagation()
console.log("这是inner")
},
cancelDef(event){
// event.preventDefault();
}
}
</script>
- 键盘事件
不再需要查找按键的keyCode值了
<!-- 键盘事件一般都用在表单类元素或者document身上 -->
<input type="text" @keyup.enter="keyEnter" />
<script>
methods:{
keyEnter(event){
// if(event.keyCode === 13){}
}
}
</script>
4. 自动收集表单数据
<div id="root">
<!-- 收集数据的时候默认收集的都是表单类元素的value值 -->
<form>
<label>
用户名:<input v-model="userName" type="text" />
</label>
<br>
<label>
密码:<input v-model="password" type="text" />
</label>
<br>
<!-- 当input是单选输入框的时候,value值要自己指定,收集到的是选中的单选框的value值 -->
<!-- 如果没有给value属性,那么获取的value值就是null -->
<label>
性别:男<input type="radio" name="sex" v-model="gender" value="male">
女 <input type="radio" name="sex" v-model="gender" value="female">
</label>
<br>
<label>
爱好:
篮球<input type="checkbox" name="hobby" value="basketball" v-model="hobbys">
乒乓球<input type="checkbox" name="hobby" value="ping-pang" v-model="hobbys">
足球<input type="checkbox" name="hobby" value="football" v-model="hobbys">
</label>
<br><br><br>
<label>
城市:
<!-- select身上的v-model收集的是选中的option的value值 -->
<select v-model="cityId">
<option value="0">Peking</option>
<option value="1">Shanghai</option>
<option value="2">Guangdong</option>
</select>
</label>
</form>
</div>
<script>
let vm = new Vue({
el:"#root",
data(){
return{
userName: "",
password: "",
gender: "male",
hobbys: ['ping-pang'],
cityId: 1
}
}
})
</script>