记 3

109 阅读5分钟

学习一 Vue 组件传值

Vue是数据驱动视图更新的框架,平时写业务时,都会把页面不同模块拆分成一个一个vue组件, 所以对于vue来说组件间的数据通信非常重要

父传子 props

props在子属性和父属性之间形成一个单向向下的绑定(单向数据流), 当父属性更新时,它会向下流向子属性,但不会反过来。这可以防止子组件意外改变父组件的状态

  • 父组件通过自定义变量传入子组件
  • 子组件利用props接收父组件值
    //使用方式一
    props:["count"],
    //使用方式二
    props:{
        count:{
            type:Number,  //type:类型规定 多种类型可以用数组[]包裹
            default:0,    //default:默认值
            require:true, //require:是否是必传,没有赋值的时候就会报错
        }
    }

  1. 绑定为响应式数据
//父组件
<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
        }
  }
}

  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元素或子组件的实例,并进行操作和交互。

  1. 获取DOM元素的引用,并调用其方法
<template>
    <input ref="inputElement" type="text" />
    <button @click="focusInput">获取焦点</button>
</template>

<script>
export default {
  methods: {
    focusInput() {
      this.$refs.inputElement.focus();
    }
  }
};
</script>
  1. 获取子组件的引用并调用子组件中的方法或访问其属性。
<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>

注意事项

  1. $refs的更新时机

$refs是在Vue实例渲染完成后才获取到的。这意味着在Vue实例的生命周期钩子函数created中是无法正确获取到$refs的。如果需要在created中使用$refs,可以通过nextTick函数来延迟执行。

created() {
  this.$nextTick(() => {
    // 在这里可以正确获取到$refs
  });
}
  1. $refs的动态更新

$refs只会在组件实例渲染的过程中被设置和更新,因此在模板中使用v-ifv-for动态生成的DOM元素,是无法通过$refs获取到的。如果需要动态更新$refs,可以使用key属性。通过给子组件添加key属性,就可以在切换子组件时,触发$refs的动态更新(更新key值 ,会触发组件自动刷新)。

学习三 Vue中的computed和watch的区别

相同点:他们两者都是观察页面数据变化的。

不同点:computed只有当依赖的数据变化时才会计算, 当数据没有变化时, 它会读取缓存数据。watch每次都需要执行函数。watch更适用于数据变化时的异步操作。

一、computed计算属性

  1. computed中的函数必须用return返回
  2. 不支持异步,当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监听

  1. watch中的函数名称必须要和data中的属性名一致,因为watch是依赖data中的属性,当data中的属性发生改变的时候,watch中的函数就会执行,他会遍历watch对象的每一个属性。

  2. watch中的函数有两个参数,前者是newValue,后者是oldValue。

  3. watch中的函数不需要调用,它不支持缓存,数据变化时,它就会触发相应的操作

  4. 支持异步监听,监听的数据必须是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适用于那些需要在属性变化时执行异步或开销较大的操作的场景。