关于Vue的一些总结
1.vue常用的指令有哪些
v-if
用于控制控制DOM的显示和隐藏,适合初次渲染某些元素不展示
<p v-if="type == 'A'">优秀</p>
<p v-else-if="type == 'B'">良好</p>
<p v-else-if="type == 'C'">及格</p>
<p v-else>差</p>
data() {
return {
type: 'A',
}
},
v-show
用于控制控制DOM的显示和隐藏,适合元素频繁切换
<button @click="changeFlag">{{ flag == true ? '隐藏' : '显示' }}</button>
<p v-show="flag">flag值为true</p>
data() {
return {
flag: true,
}
},
methods: {
changeFlag() {
this.flag = !this.flag
},
},
v-bind
用于绑定数据和元素属性,v-bind:可以简写为:
<img v-bind:src="img" width="100px" />
<img :src="img" width="100px" />
<p :class="active">绑定元素属性</p>
data() {
return {
img: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2F187db55b84ea5fbd072ceebfa6ab91408a47d8ee11cba-Bsr4iE_fw658&refer=http%3A%2F%2Fhbimg.b0.upaiyun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1655390871&t=f6e3757260e6e33ea2d5ff90edb6627a',
active: 'active',
}
},
<style lang="less">
.active {
color: pink;
}
</style>
v-on
用于为DOM绑定元素的事件监听,v-on:可以简写为@
$event 获取原生DOM的事件对象
<p>count的值为:{{ count }}</p>
<button v-on:click="add(1)">+1</button>
<button @click="sub(2)">-1</button>
<button @click="change(1,$event)">偶数为红色</button>
data() {
return {
count: 1,
}
},
methods: {
add(n) {
this.count += n
},
sub(n) {
this.count -= n
},
change(n, e) {
this.count += n
if (this.count % 2 == 0) {
e.target.style.backgroundColor = 'red'
} else {
e.target.style.backgroundColor = ''
}
},
},
v-model
用于实现表单数据的双向绑定,可用于<input>
输入框、<textarea>
文本域、<select>
选择器、<radio>
单选框、<checkbox>
多选框
<!-- input输入框 -->
<p>用户的名字是:{{ userName }}</p>
<input type="text" v-model="userName" />
<hr />
<!-- textarea文本域 -->
<textarea v-model="userName" cols="30" rows="10"></textarea>
<hr />
<!-- select选择器 -->
<p>选择的省份是:{{ city }}</p>
<select v-model="city">
<option value="">请选择</option>
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
</select>
<hr />
<!-- radio单选框 -->
<label for="male">
<input id="female" type="radio" value="male" v-model="sex" />男
</label>
<label for="male">
<input id="female" type="radio" value="female" v-model="sex" />女
</label>
<hr />
<!-- checkbox多选框 -->
<label>爱好:</label>
<label for="sing">
<input id="sing" type="checkbox" value="sing" v-model="hobbies" />唱歌
</label>
<label for="dance">
<input id="dance" type="checkbox" value="dance" v-model="hobbies" />跳舞
</label>
<label for="draw">
<input id="draw" type="checkbox" value="draw" v-model="hobbies" />画画
</label>
data() {
return {
userName: '张三',
city: 1,
sex: 'male',
hobbies: ['sing', 'dance'],
}
},
v-for
用于循环数组来渲染列表结构,item是循环的每一项,key必须具有唯一性
<table border="1" style="border-collapse: collapse" width="100px">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>
data() {
return {
list: [
{ id: 0, name: '张三' },
{ id: 1, name: '李四' },
{ id: 2, name: '王五' },
],
}
},
v-text
v-text:会把标签转义输出,只可以渲染文本
v-html
v-html:识别html标签并渲染到页面中
<p v-html="text"></p>
<p v-text="text"></p>
data() {
return {
text: '<h1>学习使我快乐!</h1>',
}
},
2.slot插槽的使用
插槽的基本用法
插槽(Slot)是vue为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽。
- 默认情况下,使用组件的时候,提供的内容都会被填充到名字为default(默认不写)的插槽之中
- 如果要把内容填充到指定名称的插槽中,需要使用v-slot:这个指令
- v-slot:后面要跟上插槽的名字
- v-slot:不能直接用在元素上,必须用在template标签上
- v-slot:可简写为 #
- template标签只起到包裹作用,不会被渲染为html元素
根组件:
<h1>根组件</h1>
<div class="box">
<!-- 引用自定义组件 -->
<Left>
<!-- <p>这是在Left组件的内容区域,声明的p标签</p> -->
<template v-slot:default>
<p>这是在Left组件的内容区域,声明的p标签</p>
</template>
</Left>
</div>
<script>
import Left from '@/components/Left.vue'
export default {
components: {
Left,
},
}
</script>
封装组件Left:
<div class="left-container">
<h3>Left组件</h3>
<!-- 声明一个插槽区域 -->
<slot></slot>
</div>
具名插槽
使用组件的时候,提供的内容都会被填充到具体名字的插槽之中
根组件:
<h1>根组件</h1>
<div class="article">
<Article>
<template #header>
<h3>画</h3>
</template>
<template #content>
<div>
<p>远看山有色,近听水无声。</p>
<p>春去花还在,人来鸟不惊。</p>
</div>
</template>
<template #footer>
<div><p>王维</p></div>
</template>
</Article>
</div>
<script>
import Article from '@/components/Article.vue'
export default {
components: {
Article,
},
}
</script>
封装组件Article:
<div class="article-container">
<h3>Article组件</h3>
<!-- 声明一个插槽区域 -->
<div class="header-box">
<slot name="header"></slot>
</div>
<div class="content-box">
<slot name="content"></slot>
</div>
<div class="footer-box">
<slot name="footer"></slot>
</div>
</div>
<style>
.article-container {
background-color: #fffff0;
padding: 10px;
flex: 1;
}
.header-box {
background-color: wheat;
min-height: 100px;
}
.content-box {
background-color: pink;
min-height: 100px;
}
.footer-box {
background-color: paleturquoise;
min-height: 100px;
}
</style>
作用域插槽
封装组件时,为预留的 <slot>
提供属性对应的值,scope用于获取的封装组件传过来的数据
根组件:
<template #footer="scope">
<div><p>王维</p></div>
<div v-for="item in scope.user" :key="item.id">
<p>{{ item.name }}</p>
</div>
</template>
封装组件Article:
<div class="footer-box">
<slot name="footer" :user="user"></slot>
</div>
data() {
return {
user: [
{ id: 0, name: '张三' },
{ id: 1, name: '李四' },
{ id: 2, name: '王五' },
],
}
},
3.vue常用的修饰符有哪些
事件修饰符
.prevent 阻止默认行为
.stop 阻止事件冒泡
.capture 以捕获模式触发当前的事件处理函数
.once 绑定的事件将只会触发1次
.self 只有在 event.target 是当前元素自身时触发事件处理函数
<!-- .prevent 阻止默认行为 -->
<a href="https://www.baidu.com/" @click.prevent="show">跳转百度页面</a>
<hr />
<!-- stop 阻止事件冒泡 -->
<div
@click="divHandle"
style="
width: 100px;
height: 100px;
line-height: 100px;
padding-left: 50px;
background-color: pink;
"
>
<button @click.stop="btnHandle">按钮</button>
</div>
<hr />
<!-- .capture 以捕获模式触发当前的事件处理函数 -->
<div
@click.capture="divHandle"
style="
width: 200px;
height: 100px;
line-height: 100px;
display: flex;
justify-content: center;
align-items: center;
background-color: pink;
"
>
<div
@click="btnHandle"
style="
width: 65px;
height: 50px;
line-height: 50px;
background-color: orange;
"
>
内部盒子
</div>
</div>
<hr />
<!-- .once 绑定的事件将只会触发1次 -->
<button @click.once="btnHandle">once事件按钮</button>
<hr />
<!-- .self 只有在 event.target 是当前元素自身时触发事件处理函数 -->
<div
@click.self="divHandle"
style="
width: 100px;
height: 100px;
line-height: 100px;
padding-left: 50px;
background-color: pink;
"
>
self
<button @click="btnHandle">按钮</button>
</div>
<hr />
methods: {
show() {
console.log('点击了a标签')
},
btnHandle() {
console.log('btnHandle')
},
divHandle() {
console.log('divHandle')
}
},
v-model修饰符
.lazy 在"change"时而非"input"时更新
.trim 自动过滤用户输入的首尾空白字符
.number 自动将用户输入的值转为数字型
<!-- .lazy 在"change"时而非"input"时更新 -->
<input type="text" v-model.lazy="msg" />
<p>{{ msg }}</p>
<!-- .trim 自动过滤用户输入的首尾空白字符 -->
<input type="text" v-model.trim="msg" />
<p>{{ msg }}</p>
<!-- .number 自动将用户输入的值转为数字型 -->
<input type="text" v-model.number="age" />
<p>{{ age }}</p>
data() {
return {
msg: '',
age: '',
}
},
按键修饰符
Vue 提供了绝大多数常用的按键码,有enter、esc、delete、tab、space、up、down、left、right等,具体可查看Vue官网
<!-- 按键修饰符 -->
<div>
<input type="text" @keyup.enter="clearInput" />
<input type="text" @keyup.esc="clearInput($event)" />
</div>
methods: {
clearInput(e) {
console.log('触发了clearInput')
e.target.value = ''
},
},
4.watch侦听器
watch侦听器用来监视数据的变化,从而针对数据的变化做特定的操作。
注意: 侦听对象的子属性,必须包裹一层单引号。
watch的使用
<label>用户名:<input type="text" v-model="userName" /></label>
<label>用户名:<input type="text" v-model="info.userName" /></label>
data() {
return {
userName: 'admin',
info: {
userName: 'admin',
},
}
},
watch: {
userName(newVal, oldVal) {
console.log(newVal, oldVal)
},
// 侦听对象的子属性,必须包裹一层单引号
'info.userName'(newVal, oldVal) {
console.log(newVal, oldVal)
},
}
immediate选项
通过immediate选项,让侦听器自动触发一次。
watch: {
userName: {
handler(newVal, oldVal) {
console.log(newVal, oldVal)
},
immediate: true,
},
},
deep选项
如果侦听的是一个对象,如果对象中的属性发生了变化,不会触发侦听器。可以通过deep选项,让侦听器深度监听对象每个属性的变化。
<label>用户名:<input type="text" v-model="info.userName" /></label>
watch: {
info: {
handler(newVal) {
console.log(newVal)
},
deep: true,
},
}
5.computed计算属性
计算属性具有缓存功能,当它依赖一个或多个状态值发生变化时,computed会自动计算,返回新的状态值。可以理解计算属性是对data中已有的数据加工处理之后形成新的数据。
注意: 计算属性中动态计算返回的结果可以被模板结构和methods方法使用。
注意: 计算属性中不能返回异步操作的结果。
<h3>{{ showResult }}</h3>
data() {
return {
userName: '张三',
age: 18,
}
},
computed: {
showResult() {
return '我的名字叫' + this.userName + ',今年' + this.age + '岁!'
},
},
6.vue中父子组件通信
父向子传值-自定义属性
步骤:
- 创建一个Son子组件
- 在Father父组件中引用子组件
<Son></Son>
<Son>
中绑定自定义属性,例如 :num=“num”- 在Son子组件设置props属性
父组件
<div class="Father">
<h3>父组件</h3>
<p>{{ num }}</p>
<!-- 通过绑定自定义属性向子组件传值 -->
<Son :num="num"></Son>
</div>
<script>
import Son from '@/components/Son.vue'
export default {
name: 'Father',
components: {
Son,
},
data() {
return {
num: 0,
}
}
}
</script>
子组件
<div class="Son">
<h3>子组件</h3>
<p>父组件传过来的num值为:{{ num }}</p>
</div>
<script>
export default {
name: 'Son',
// 通过props接收父组件传过来的自定义属性
props: {
num: {
type: Number, //设置类型
default: 0, //设置默认值
},
}
}
</script>
子向父传值-自定义事件
步骤:
- Son子组件绑定事件方法,例如 add()
- 在add()方法中,通过使用 e m i t ( ) 触 发 父 组 件 的 自 定 义 事 件 c h a n g e N u m , 并 传 值 v a l , 例 如 t h i s . emit()触发父组件的自定义事件changeNum,并传值val,例如 this. emit()触发父组件的自定义事件changeNum,并传值val,例如this.emit(‘changeNum’, 1)
- 在父组件的
<Son>
中绑定自定义事件,例如 @changeNum=‘getSonNum’ - 在父组件设置getSonNum方法,接收子组件的值并修改数据
父组件
<Son :num="num" @changeNum="getSonNum"></Son>
methods: {
getSonNum(val) {
console.log(val)
this.num += val
}
},
子组件
<div>
<button @click="add">父组件传过来的num值+1</button>
</div>
methods: {
add() {
this.$emit('changeNum', 1)
}
},
7.vuex的使用
Vuex是什么
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。
1. vuxe的优点
a. 能够在Vuex中集中管理共享的数居,易于开发和后期维护
b. 能够高效地实现组件之间的数据共享,提高开发效率
c. 存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步
2. vuex解决了什么问题
多个组件依赖或要改变同一状态时,对于多层嵌套的组件的传参将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
3. 什么样的数据适合存储到Vuex中
一般情况下,只有组件之间共享的数据,才有必要存储到vuex中;对于组件中的私有数据,依旧存储在组件自身的data中即可。
4. 什么时候适合使用vuex
多个组件依赖或要改变同一状态;多个组件使用同一方法。
5. vuex中的五个核心属性
state、getters、mutations、actions、modules、(plugins)
State 数据源
State提供唯一的公共数据源,所有共享的数据都要统一放到 Store的 State I中进行存储。
- this.$store.state.全局数据名称 访问
state: {
count: 0
},
<h3>当前最新的count值为:{{ $store.state.count }}</h3>
- mapState 映射为计算属性
<h3>当前最新的count值为:{{ count }}</h3>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['count']),
},
}
Mutations 变更store中的数据
Mutations用于变更 Store中的数据。
注意: 只有 mutations里的函数,才有权利修改 state 的数据
注意: mutations里不能包含异步操作。
- this.$store.commit() 触发 mutations
mutations: {
addN (state, step) {
state.count += step
}
}
<button @click="btnHandler(3)">+N</button>
methods: {
btnHandler(n) {
this.$store.commit('addN', n)
},
}
- MapMutations 映射为方法
mutations: {
subN (state, step) {
state.count -= step
}
}
<button @click="subN(3)">-N</button>
import { mapMutations } from 'vuex'
methods: {
...mapMutations(['subN']),
}
Actions 专门处理异步操作
Actions用于处理异步任务。
注意: 在Actions 中不能直接修改 state中的数据,要通过 mutations修改。
- this.$store.dispatch 触发 Actions
mutations: {
// 1. mutations修改 state中的数据
addN (state, step) {
state.count += step
}
},
actions: {
// 2. Actions处理异步任务
addNAsync (context, step) {
setTimeout(() => {
context.commit('addN', step)
}, 1000)
},
},
<button @click="btnHandlerAsync(3)">+AsyncN</button>
methods: {
// 3. this.$store.dispatch() 触发 actions
btnHandlerAsync(n) {
this.$store.dispatch('addNAsync', n)
},
},
- mapActions 映射为方法
mutations: {
// 1. mutations修改 state中的数据
subN (state, step) {
state.count -= step
}
},
actions: {
// 2. Actions处理异步任务
subNAsync (context, step) {
setTimeout(() => {
context.commit('subN', step)
}, 1000)
}
}
<button @click="subNAsync(3)">-N Async</button>
// 1.导入辅助函数 mapActions
import { mapActions } from 'vuex'
methods: {
// 2.mapActions映射为方法
...mapActions(['subNAsync']),
}
Getter 加工处理数据
Getter 用于对 Store中的数据进行加工处理形成新的数据。
注意: Getter可以对 Store中已有的数据加工处理之后形成新的数据,类似Vue的计算属性。
注意: Store中数据发生变化,Getter 的数据也会跟着变化。
- 通过 this.$store.getters.名称 访问
state: {
count: 0
},
getters: {
showNum (state) {
return ' 当前最新的数量是【' + state.count + '】'
}
},
<h3>{{ $store.getters.showNum }}</h3>
- mapGetters 映射为计算属性
<h3>{{ showNum }}</h3>
// 1.导入辅助函数 mapGetters
import { mapGetters } from 'vuex'
// 2.mapGetters映射为计算属性
computed: {
...mapGetters(['showNum']),
}