上一讲主要介绍了Vue的环境、项目等的配置,今天来回顾一下Vue的一些基础语法。
Vue项目的目录结构
首先看一下昨天新建的Vue项目的目录结构:
node_modules文件夹昨天说过了,是存放项目相关依赖的文件夹,与package.json相互对应。public文件夹存放项目首页index.html等文件,暂时先不用管。src中主要放置项目的静态资源文件,其中assets存放图片、css等文件,components存放子组件。App.vue为父组件,也叫根组件,通过main.js引入到项目中。为方便介绍Vue基本语法,这里先把子组件去掉,并对App.vue进行改造,只保留基础代码语句。
<template>
<div id="app">
{{msg}}
</div>
</template>
<script>
export default {
name: 'app',
data(){
return{
msg:"hello vue!"
}
}
}
</script>
基本语法
- 双大括号可以和下面的msg内容绑定,代码见上,没啥好说的这块。
- data中传递一个对象,用 对象.属性 方法调用:
<template>
<div id="app">
{{obj.name}}
</div>
</template>
<script>
export default {
name: 'app',
data(){
return{
obj:{
name:"张三"
}
}
}
}
</script>
- data中传递数组,使用v-for进行循环遍历数组内容,其中v-for中的内容,item可以任意取名,list和下面data中的数组名一致:
(1)简单数组:
<template>
<div id="app">
<ul>
<li v-for="item in list">
{{item}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return{
list:['111','222','333','444','555']
}
}
}
</script>
(2)简单对象数组:
<template>
<div id="app">
<ul>
<li v-for="item in list">
{{item.title}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return{
list:[
{title:"11111"},
{title:"22222"},
{title:"33333"}
]
}
}
}
</script>
(3)复杂对象数组:
<template>
<div id="app">
<ul>
<li v-for="item in list" :key="item.title">
{{item.title}}
<ul>
<li v-for="news in item.list" :key="news.title">
{{news.title}}
</li>
</ul>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return{
list:[
{
title:"国内新闻",
list:[
{title:'国内新闻1'},
{title:'国内新闻2'},
{title:'国内新闻3'}
]
},
{
title:"国外新闻",
list:[
{title:'国外新闻1'},
{title:'国外新闻2'},
{title:'国外新闻3'}
]
}
]
}
}
}
</script>
注意:
- 在使用VScode编辑器vue开发过程中,v-for在Eslint的规则检查下出现报错:Elements in iteration expect to have ‘v-bind:key’ directives。这是因为我们安装了ESLint插件,对vue进行了eslint检查,其实并不是语法错误,所以只需将这个规则检查屏蔽掉即可,具体操作如下:
文件 –> 首选项 –> 设置 –> 在搜索框中输入:vetur.validation.template–> 找到vetur.validation.template:true –> 将vetur.validation.template:true在右栏框中进行重置为false就不报错了。 - 对于复杂对象数组使用v-for时,建议绑定相应的key,即绑定能体现出该项唯一性的属性,比如上面代码中的title属性,否则命令行中会报错,但是程序没问题,可正常运行,但有可能会出现未知bug。
组件的key属性
- 官方推荐我们使用v-for时 ,给对应元素或组件添加一个:key属性。
- 为什么需要这个key属性?
- 这个其实和Vue的虚拟dom的Diff算法有关系
- 当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点
- 我么希望在B和C之间加一个F,Diff算法默认执行起来是这样的
- 即把C更新成F,D更新成C,E更新成D,最后再插入E。
- 所以我们需要使用key来给每个节点做一个唯一标识
- Diff算法就可以正确的识别此节点
- 找到正确的位置区插入新的节点
- 所以一句话,key的作用主要是为了高效的更新虚拟DOM。
- v-if、v-else-if、v-else
<template>
<div id="app">
<h2 v-if="score>90">优秀</h2>
<h2 v-else-if="score>80">良好</h2>
<h2 v-else-if="score>60">及格</h2>
<h2 v-else>不及格</h2>
</div>
</template>
<script>
export default {
data() {
return {
score: 90
}
}
}
</script>
推荐写法:
<template>
<div id="app">
<h1>{{ result }}</h1>
</div>
</template>
<script>
export default {
data() {
return {
score: 99
}
},
computed: {
result() {
let showMessage = ''
if (this.score >= 90){
showMessage = '优秀'
}
else if (this.score >= 80){
showMessage = '良好'
}
// ......
return showMessage
}
},
}
</script>
补充:v-show
- v-show的用法和v-if非常相似,也用于决定一个元素是否被渲染
- v-if和v-show对比
- v-if和v-show都可以决定一个元素是否渲染,那么开发中我们如何选择?
- v-if当条件为false时,压根不会有对应的元素在DOM中
- v-show当条件为false时,仅仅是将元素display属性设置为none而已
- 开发中如何选择?
- 当需要在显示与隐藏之间切片很频繁时,使用v-show
- 当只有一次切换时,通过使用v-if
- v-bind绑定属性:
对于一个标签的属性,可以用data中的属性绑定对应标签属性,写法是在标签属性前加v-bind:或者:,实例代码如下:
<template>
<div id="app">
<div :title="title_1">鼠标瞄上去看一眼</div>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
title_1:"我是一个title"
}
}
}
</script>
title属性的意思就是鼠标移上去会有提示。同样也可以绑定其他属性,例如img的src等等。
- v-html转换成HTML元素:
使用v-html可以将data中的html内容转换成真正的html标签格式内容,比如:
<template>
<div id="app">
<div v-html="h"></div>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
h:"<h2>我是一个h2标签</h2>"
}
}
}
</script>
- v-text 绑定数据的另一种方法
本文一开始就讲{{ }}方式可以绑定data中的属性值,v-text也可以绑定,例如:
<template>
<div id="app">
<h1 v-text="msg"></h1>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
msg:"hello vue"
}
}
}
</script>
h1标签中就有msg对应内容了。
- 绑定class元素样式
<template>
<div id="app">
<div :class="{'red':flag}">我是红色的div</div>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
flag:true
}
}
}
</script>
<style>
.red{
color: red
}
</style>
注意:class中的{ }一定要加,属性名的单引号加不加都行。
补充: ul>li 中不同li不同style:
<template>
<div id="app">
<ul>
<li v-for="(item, key) in list" :key="item" :class="{red:key==0,blue:key==1}">{{item}}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
list:['111','222','333']
}
}
}
</script>
<style>
.red{
color: red
}
.blue{
color:blue
}
</style>
- 绑定style
<template>
<div id="app">
<div :style="{'width':width_val+'px', 'height':height_val+'px','background':background_color}">我是一个div</div>
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
width_val:200,
height_val:100,
background_color:'red'
}
}
}
</script>
注意:style中的{ }一定要加,属性名的单引号加不加都行,涉及到高度、宽度等别忘了加单位。
- v-on:click添加点击事件:
v-on可以简写成@,绑定的方法写在methods里面。
<template>
<div id="app">
<input type="button" value="方法1" v-on:click="run1()">
<input type="button" value="方法2" @click="run2()">
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
msg:"你好Vue"
}
},
methods:{
// 定义方法的两种方式
run1:function(){
alert("这是一个方法")
},
run2(){
alert("这是另一个方法")
}
}
}
</script>
- 事件对象:
<template>
<div id="app">
<!-- 1. 事件调用的方法没有参数 -->
<button @click="btn1Click()">按钮1</button>
<button @click="btn1Click">按钮1</button>
<!-- 2. 在事件定义时,写方法时省略了小括号,但是方法本身是需要一个参数的,这个时候,Vue会默认将浏览器生产的event事件对象作为参数传入到方法 -->
<button @click="btn2Click(123)">按钮2</button>
<button @click="btn2Click()">按钮2</button> <!-- undefined -->
<button @click="btn2Click">按钮2</button> <!-- MouseEvent -->
<!-- 3. 方法定义时,我们需要event对象,同时又需要其他参数 -->
<!-- 在调用方式,如何手动获取到浏览器参数的event对象:通过$event传入事件 -->
<button @click="btn3Click(123, $event)">按钮3</button>
</div>
</template>
<script>
export default {
name: 'app',
methods:{
btn1Click() {
console.log("btn1click")
},
btn2Click(event) {
console.log(event)
},
btn3Click(abc,event){
console.log(abc, event)
}
}
}
</script>
- v-on修饰符
- Vue提供了修饰符来帮助我们方便的处理一些事件:
- .stop 调用event.stopPropagation()
- .prevent 调用 event.preventDefault()
- .{keyCode | keyAlias} 只当事件是从特定键触发时才触发回调
- .native 监听组件根组件的原生事件
- .once 只触发一次回调
<template>
<div id="app">
<!-- 1. stop修饰符的使用(阻止事件冒泡) -->
<div @click="divclick">
<button @click.stop="btnclick">点击</button>
</div>
<!-- 2. prevent修饰符的使用(阻止默认事件) -->
<form action="xxx">
<input type='submit' value="提交" @click.prevent="submitClick"/>
</form>
<!-- 3. 监听某个键盘的键帽(键别名) -->
<input type="text" @keyup.enter="keyUp" /> <!-- 回车 -->
<!-- 3. 监听某个键盘的键帽(键代码) -->
<input type="text" @keyup.13="keyUp" /> <!-- 回车 -->
<!-- 4. 自定义组件监听 -->
<v-cpn @click.native="cpnClick"></v-cpn>
<!-- 5. once修饰符的使用(只能点击一次) -->
<button @click.once="btn2click"></button>
</div>
</template>
<script>
export default {
methods: {
btnclick() {
console.log('btnclick');
},
divclick() {
console.log('divclick');
},
submitClick() {
console.log('submitClick');
},
keyUp() {
console.log('KeyUp');
},
cpnClick() {
console.log('cpnClick');
},
btn2click() {
console.log('btn2click');
},
}
}
</script>
登陆切换小案例及input复用问题:
-
小问题:
- 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容
- 但是按道理讲,我们应该切换到另外一个input元素中了。
- 在另一个input元素中,我们并没有输入内容,为什么会出现这个问题呢?
-
问题解答:
- 这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素
- 在上面的案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了
-
解决方案:
- 如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
- 并且我们需要保证key的不同
<template>
<div id="app">
<span v-if="isUser">
<label for="username">用户账号</label>
<input type="text" id="username" placeholder="用户账号" key="username" />
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" id="email" placeholder="用户邮箱" key="email" />
</span>
<button @click="isUser = !isUser">切换类型</button>
</div>
</template>
<script>
export default {
data() {
return {
isUser: true
}
}
}
</script>