vue必会API盘点
一、数据相关API
1.1 Vue.set
向响应式对象中添加一个属性,并确保这个新属性同样是响应式,且触发视图更新
使用方法:Vue.set( target, propertyName/index, value )
范例:批量设置商品价格
<!-- 批量更新价格 -->
<p>
<input type="text" v-model.number="price">
<button @click="batchUpdate">批量更新价格</button>
</p>
<div v-else>
<div v-for="item in foods"
:key="item.name"
:style="{backgroundColor:selectedFood == item.name ? '#ddd' : 'transparent' }"
@click="selectedFood = item.name"
>
{{item.name}}- ¥{{item.price}}
</div>
</div>
<script>
//模拟异步数据调用
function getData(){
return new Promise(resolve => {
setTimeout(()=>{
resolve([
{
name:'萝卜',
},
{
name:'白菜',
}
])
},2000);
});
}
const app = new Vue({
el: "#app",
data() {
return {
foodList: [],
price:0
};
},
async created () {
const foodList = await getData();
this.foodList = foodList;
//批量更新商品的价格
this.batchUpdate();
},
methods: {
batchUpdate(){
this.foodList.forEach(item=>{
// item.price = this.price; //no ok 数据更新,但是页面没有更新
Vue.set(item,'price',this.price); //ok
this.$set(item,'price',this.price); //ok
});
}
},
});
</script>
1.2 Vue.delete
删除对象的属性。如果对象是响应式的,确保删除能触发更新视图。
使用方法:Vue.delete( target, propertyName/index )
delete obj['property'] //no ok
vm.$set( target, propertyName/index, value )
这是全局 Vue.set 的别名。
vm.$delete( target, propertyName/index )
这是全局 Vue.delete 的别名。
二、事件相关API
vm:表示的是这是一个vue的具体的实例,不是它的构造函数
2.1 vm.$on
监听当前实例上的自定义事件。 事件可以由 vm.$emit 触发。回调函数会接收所有传入事件触发函数的额外参数。
用的不多,主要是在模板中可以通过 @... 的方式来进行监听
@test = "callback" 事件的监听者,事件的派发者,是同一个实例
vm.$on('test', function (msg) {
console.log(msg)
})
2.2 vm.$emit
触发当前实例上的事件。附加参数都会传给监听器回调。
在组件内部给老爹派发事件
vm.$emit('test', 'hi')
2.3 典型应用:事件总线
通过在Vue原型上添加一个Vue实例作为事件总线,实现组件间通信,而不受组件间关系的影响
Vue.prototype.$bus = new Vue();
这样做可以在任意组件中使用this.$bus访问到该Vue实例
没有引入vuex之前非常好的一个解决方案
范例:批量关闭多个消息弹窗
/* 重构样式:提取出.success,并添加.warning */
<style>
.message-box {
padding: 10px 20px;
}
.success {
background: #4fc08d;
border: 1px solid #42b983;
}
.warning {
background: #f66;
border: 1px solid #d63200;
}
</style>
<!-- 给之前新增成功消息添加.success -->
<message :show.sync="isShow" class="success">
<template v-slot:title="slotProps">
<strong>{{slotProps.title}}</strong>
</template>
<template> 新增成功! </template>
</message>
<!--新增警告提示窗-->
<message :show.sync="showWarn" class="warning">
<template>
<strong>警告</strong>
</template>
<template> 请输入课程的名称 </template>
</message>
const app = new Vue({
el: "#app",
data() {
return {
isShow: false,
showWarn: false,
};
},
methods: {
addFood(show) {
if (this.food) {
this.foodList.push({name:this.food});
this.food = "";
//显示成功弹窗
this.isShow = show;
} else {
//显示错误信息
this.showWarn = show;
}
},
},
});
下面实现功能:
<script>
//弹窗组件
Vue.component("message", {
props: ["show"], //使用props弹窗是否展示是由父组件决定的
template: `
<div class="message-box" v-if="show">
<!--具名插槽-->
<slot name="title" title="来自message的标题">默认标题</slot>
<!--通过slot获取父组件传入的内容-->
<slot></slot>
<span class="message-box-colse" @click="$emit('update:show',false)">X</span>
</div>
`,
mounted(){
//挂载之后,使用总线 $bus 去监听,监听者不是它自己,而是总线,
//总线会派发 message-close
//而如果我收到一个 message-close , 就执行一个方法,派发一下,让老爹去修改这个属性
//监听关闭事件
this.$bus.$on('message-close',() => {
this.$emit('update:show',false);//复制template中关闭按钮的事件
})
}
});
</script>
<!--派发关闭事件-->
<div class="toolbar">
<button @click="$bus.$emit('message-close')">清空提示框</button>
</div>
2.4 vm.$once
监听一个自定义事件,但是只触发一次。一旦触发之后,监听器就会被移除。
2.5 vm.$off
移除自定义事件监听器。
-
如果没有提供参数,则移除所有的事件监听器;
-
如果只提供了事件,则移除该事件所有的监听器;
-
如果同时提供了事件与回调,则只移除这个回调的监听器。
vm.$off() //移除所有的事件监听器
vm.$off('test') //移除该事件所有的监听器
vm.$off('test',callback) //只移除这个回调的监听器
三、组件或元素引用
3.1 ref 和 vm.$refs
ref
被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的$refs
对象上。如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子组件上,引用就指向组件实例。
范例:设置输入框焦点
<input :value="value" ... ref="inp"/>
<script>
mounted () {
//获取焦点事件
this.$refs.inp.focus();
}
</script>
范例:改造message组件用打开、关闭方法控制显示
//弹窗组件
Vue.component("message", {
// props: ["show"], //使用props弹窗是否展示是由父组件决定的
//show这个状态不是自己维护的,是老爹传递的
//假设这个状态由自己维护,自己修改
//需要暴露一个api,一个关闭方法,让老爹可以直接调这个关闭方法
//改造:
//1.注释props
//2.在data中声明show,并给默认值
//3.暴露给外界一个关闭方法
//4.在template中关闭事件给为 @click="toggle" ,在mounted中改为 this.toggle()
//5.老爹 - app中 去掉isShow,showWarn这两个属性
//6.<message>中
//6.1 去掉 :show.sync="isShow" :show.sync="showWarn"
//6.2 增加 ref="msgSuccess" ref="msgWarning"
//7.app 的 addFood方法中
// 去掉 this.isShow = show;
// 改为 this.refs.msgSuccess.toggle(); this.refs.msgWarning.toggle();
data() {
return {
show: false
}
},
template: `
<div class="message-box" v-if="show">
<!--具名插槽-->
<slot name="title" title="来自message的标题">默认标题</slot>
<!--通过slot获取父组件传入的内容-->
<slot></slot>
<span class="message-box-colse" @click="toggle">X</span>
</div>
`,
//修改message-close回调为toggle
mounted(){
this.$bus.$on('message-close',() => {
// this.$emit('update:show',false);
this.toggle();
})
},
//增加toggle方法维护show状态
methods: {
toggle() {
this.show = !this.show;
}
},
});
<message ref="msgSuccess" class="success">
<template v-slot:title="slotProps">
<strong>{{slotProps.title}}</strong>
</template>
<template> 新增成功! </template>
</message>
<message ref="msgWarning" class="warning">
<template>
<strong>警告</strong>
</template>
<template> 请输入课程的名称 </template>
</message>
const app = new Vue({
el: "#app",
data() {
return {
// isShow: false,
// showWarn: false,
};
},
methods: {
//使用 refs.msg 访问自定义组件
addFood(show) {
if (this.food) {
//显示成功弹窗
// this.isShow = show;
this.refs.msgSuccess.toggle();
} else {
//显示错误信息
// this.showWarn = show;
this.refs.msgWarning.toggle();
}
},
},
});
注意:
- ref 是作为渲染结果被创建的,在初始渲染时不能访问它们
$refs
不是响应式的,不要试图用它在模板中做数据绑定- 当
v-for
用于元素或组件时,引用信息将是包含 DOM 节点或组件实例的数组