学习一 Vue 组件传值
Vue是数据驱动视图更新的框架,平时写业务时,都会把页面不同模块拆分成一个一个vue组件, 所以对于vue来说组件间的数据通信非常重要
父传子 props
props在子属性和父属性之间形成一个单向向下的绑定(单向数据流), 当父属性更新时,它会向下流向子属性,但不会反过来。这可以防止子组件意外改变父组件的状态
- 父组件通过自定义变量传入子组件
- 子组件利用
props接收父组件值
//使用方式一
props:["count"],
//使用方式二
props:{
count:{
type:Number, //type:类型规定 多种类型可以用数组[]包裹
default:0, //default:默认值
require:true, //require:是否是必传,没有赋值的时候就会报错
}
}
- 绑定为响应式数据
//父组件
<template>
<button @click="count+=1">要传递的值{{count}}</button>
//第三步通过v-bind动态传入子组件
<Child :count="count"></Child>
</template>
<script>
//第一步导入组件
import Child from "../child/index.vue"
export default {
//第二步组件注册
components:{
Child,
},
data () {
return {
count: 1
}
}
}
- 直接使用
//父组件同上
//子组件
<template>
// 第二步在页面中使用
<div>接收父组件传值:{{count}}</div>
</template>
<script>
export default {
//第一步利用 props 接收
//可以直接在页面中使用,但不可修改;修改需要先将 props 中的数据赋值给 data 中的变量
// props:["count"],
props:{
count:{
type:Number, //类型
default:0, //默认值
require:true, //是否必填
}
},
}
子传父 $emit
- 在子组件中通过
$emit触发方法传值给父组件 - 在父页面中的子组件标签中自定义事件接收
emit 中第一个参数是在父页面中接收的事件名称,第二个参数是要传递的数据
1、当该子组件被点击时,触发子组件内事件。
2、事件内包含要执行的操作及$emit函数
3、$emit函数会调用父组件里子组件标签中名为第一个参数的事件,并将第二个参数的值传过去。
3、父组件中被调用的事件会被触发。
//子组件
<template>
<button @click="give">传递给父组件</button>
</template>
<script>
export default {
methods:{
give(){
//第一步调用 $emit 传递参数
this.$emit("child",`我是子组件值+ ${new Date().getTime()}`)
}
}
}
// 父组件
<template>
// 第三步 使用接收到的数据
<div>我是接收到的子组件的值:{{this.childValue}}</div>
// 第一步 监听子组件中自定义事件
<Child :count="count" @child="accept"></Child>
</template>
<script>
import Child from "../child/index.vue"
export default {
components:{
Child,
},
data () {
return {
childValue:"",
}
},
methods:{
// 第二步 accept 接收 emit 传递的值
accept(obj){
this.childValue = obj
}
}
}
同级传值 EventBus(也可由父中转(子传父=>父传子),或直接使用Vuex)
EventBus实际是通过额外的vue实例来做数据存储
- 在components文件中新建一个 js 文件,页面中导入Vue实例,然后导出一个
new Vue() - 在需要兄弟之间传值的组件中导入这个文件
- 传值时通过导入的文件调用
$emit实现($emit("事件名称",需要传递的值)) - 接收时通过导入的文件调用
$on通过回调函数实现
// component 文件夹中新建 eventBus.js 文件,用来实现兄弟组件通信
import Vue from "vue";
export default new Vue()
// 组件 A
<template>
<button @click="send">A组件给B组件传值</button>
</template>
<script>
import bus from "../eventBus";
export default {
methods: {
send() {
bus.$emit("share", `我是A组件+ ${new Date().getTime()}`);
},
},
};
</script>
// 组件 B
<template>
<div>接收A组件的值{{this.accept}}</div>
</template>
<script>
import bus from "../eventBus"
export default {
data(){
return{
accept:''
}
},
mounted(){
bus.$on("share",val=>{
this.accept = val
})
}
}
</script>
学习二 Vue 中的 $refs
$refs用于访问DOM元素或子组件的实例,并进行操作和交互。
- 获取DOM元素的引用,并调用其方法
<template>
<input ref="inputElement" type="text" />
<button @click="focusInput">获取焦点</button>
</template>
<script>
export default {
methods: {
focusInput() {
this.$refs.inputElement.focus();
}
}
};
</script>
- 获取子组件的引用并调用子组件中的方法或访问其属性。
<template>
<child-component ref="childComponent"></child-component>
<button @click="callChildMethod">调用子组件方法</button>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
callChildMethod() {
this.$refs.childComponent.childMethod();
}
}
};
</script>
注意事项
$refs的更新时机
$refs是在Vue实例渲染完成后才获取到的。这意味着在Vue实例的生命周期钩子函数created中是无法正确获取到$refs的。如果需要在created中使用$refs,可以通过nextTick函数来延迟执行。
created() {
this.$nextTick(() => {
// 在这里可以正确获取到$refs
});
}
$refs的动态更新
$refs只会在组件实例渲染的过程中被设置和更新,因此在模板中使用v-if或v-for动态生成的DOM元素,是无法通过$refs获取到的。如果需要动态更新$refs,可以使用key属性。通过给子组件添加key属性,就可以在切换子组件时,触发$refs的动态更新(更新key值 ,会触发组件自动刷新)。
学习三 Vue中的computed和watch的区别
相同点:他们两者都是观察页面数据变化的。
不同点:computed只有当依赖的数据变化时才会计算, 当数据没有变化时, 它会读取缓存数据。watch每次都需要执行函数。watch更适用于数据变化时的异步操作。
一、computed计算属性
- computed中的函数必须用return返回。
- 不支持异步,当Computed中有异步操作时,无法监听数据的变化
优点
-
简洁方便:computed 计算属性的定义方式和普通属性一样,不需要额外的方法调用。
-
自动缓存:computed 的计算结果会被缓存起来,只有当依赖的数据发生变化时,才会重新计算,减少了重复计算的开销。
-
响应式:computed 的计算结果是响应式的,当依赖的数据发生变化时,会自动更新计算结果,并触发相关的视图更新。
使用场景:当一个值受多个属性影响的时候-------购物车商品结算(多个属性求和)
//html部分
<div id="app">
<p>原来的数据: {{ msg }}</p>
<p>反转后的数据为: {{ reversedMsg }}</p>
</div>
//js部分
var vm = new Vue({
el: '#app',
data: {
msg: 'hello'
},
computed: {
reversedMsg() {
return this.msg.split('').reverse().join('')
}
}
});
以上代码中,使用computed来进行计算属性值,vm.reversedMsg 的值依赖于 vm.msg 的值,当vm.msg的值发生改变时, vm.reversedMsg 的值也会得到更新。
二、watch监听
-
watch中的函数名称必须要和data中的属性名一致,因为watch是依赖data中的属性,当data中的属性发生改变的时候,watch中的函数就会执行,他会遍历
watch对象的每一个属性。 -
watch中的函数有两个参数,前者是newValue,后者是oldValue。
-
watch中的函数不需要调用,它不支持缓存,数据变化时,它就会触发相应的操作
-
支持异步监听,监听的数据必须是data中声明的或者父组件传递过来的props中的数据,当发生变化时,会触发其他操作,有两个参数:
immediate:组件加载立即触发回调函数。
watch有一个特点: 第一次初始化页面是不会执行属性监听的, 只有当依赖的data的数据值发生改变的时候才会执行监听计算,设置该属性为true,可以在第一次初始化页面的时候就执行监听。deep:深度监听,在复杂数据类型中使用。例如数组中的对象发生变化时,发现数据内部的变化。需要注意的是,deep无法监听到数组和对象内部的变化。
优点
-
灵活性:watch 可以监听任意数据的变化,不限于计算属性的依赖关系。
-
异步操作:watch 可以执行异步操作,比如发送网络请求或者执行复杂的计算。
-
更深入的监听:watch 可以监听对象或数组的变化,并通过深度监听选项来实现。
使用场景:当一条数据的更改影响到多条数据的时候--------搜索框
<div id="app">
<p>个人信息情况: {{ basicMsg }}</p>
<p>今年的年龄: <input type="text" v-model="age" /></p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
basicMsg: '',
age: 31,
single: '单身'
},
watch: {
age(newVal, oldVal) {
this.basicMsg = '今年' + newVal + '岁' + ' ' + this.single;
}
}
});
</script>
computed适用于那些需要根据其他属性计算出一个新值的场景,而watch适用于那些需要在属性变化时执行异步或开销较大的操作的场景。