Vue组件与组件通信

首先回答一下上篇文章的问题

1.为什么v-for的key不用索引呢?

首先,:key是用于给v-for颁发唯一标识的,用于性能优化,其值最好是不重复且唯一.

如果使用索引作为key的值,当往数组中再插入一个值,或者删除一个值的时候,索引就会跟随值的改变而改变,此时v-for渲染出来的位置就有可能打乱,比如删除一个当前值,结果删除了后面那个

所以,在使用:key时最好使用一个唯一的,不重复的值,比如id,这样就能保证准确

2.数组更新为何有时v-for不触发呢?

vue底层只能检测到数组顺序/位置改变/数量变化,但值被重新赋予,vue不能检测,例如字面量方法直接把值改了,根本检测不到

要解决这个问题,使用this.$set或Vue.set(),两个方法都可以解决


一.组件

1.什么是组件

组件是可复用的Vue实例,可以封装标签,样式和js代码,把页面可重复使用的部分封装为组件,方便项目开发与维护

2.如何使用

第一步:注册

在项目文件夹中的components文件夹中创建需要封装的组件(即vue文件)

Vue组件与组件通信

在此创建test.vue文件,

第二步:引入

Vue组件与组件通信

 第三步:注册

两种注册方式

1.全局注册

Vue组件与组件通信

2.局部注册

Vue组件与组件通信 

第四步:使用

根据注册时的组件名,用作标签

Vue组件与组件通信 

3.scoped作用

给组件内的style标签增加scoped可以让样式只在当前组件内生效

原理:增加scoped属性后,就会在对应组件的标签上增加一个随机生成的data-v开头带随机哈希值的属性,这样就能保证样式只对当前组件生效.


二.通信

1.父向子传值

子组件 props 接收值

例如:父组件中定义变量str,在组件标签上将值传递到子组件上

<template>
  <div>
    <test :abc="str"> </test>
  </div>
</template>

<script>
import test from "./components/test.vue";
// import vue from "vue";
// vue.component("test", test);
export default {
  components: {
    test,
  },
  data() {
    return {
      str: "我是传过去的值",
    };
  },
};
</script>

<style>
</style>

 子组件使用props接收变量,变量名需要与父组件传递来的属性名相同

<template>
  <div>
    {{ abc }}
  </div>
</template>

<script>
export default {
  props: ["abc"],
};
</script>

<style>
</style>

2.子向父通信 配合v-for循环

例如:

父组件:

<template>
  <div>
    <test v-for="(item, index) in arr" :key="index" :val='item'> </test>
  </div>
</template>

<script>
import test from "./components/test.vue";
// import vue from "vue";
// vue.component("test", test);
export default {
  components: {
    test,
  },
  data() {
    return {
      arr: [1, 23, 4, 324, 5421, 23421, 24, 234, 24, 42],
    };
  },
};
</script>

<style>
</style>

子组件:

<template>
  <div>
    {{ val }}
  </div>
</template>

<script>
export default {
  props: ["val"],
};
</script>

<style>
</style>

注:也可以直接将数组传进子组件,然后在子组件中遍历

3.单向数据流

在vue中需要遵循单向数据流的原则

  1. 父组件的数据发生改变,子组件会跟随改变
  2. 子组件不能直接修改父组件传递来的props,props是只读的

注意:如果父组件传给子组件一个对象,或一个数组,引用类型数据是不会报错的,因为父组件相当于传了一个地址过去,互相更新

总结:

props变量本身是只读的不能重新赋值

从父组件->子组件的数据流向叫单向数据流

子组件修改不通知父级,会造成数据不一致

4.组件通信-子向父

将子组件的值传递给父级使用,再通过单向数据流影响子组件

使用自定义事件名

例如:

父组件:

<template>
  <div>
    <!--1.由此处开始,父组件将数组内的值传给子组件 :val='item'-->
    <!-- 7.自定义事件在这里生效,触发delFn方法 -->
    <!--10.更新新数组,影响子组件 -->
    <test
      v-for="(item, index) in arr"
      :key="index"
      :val="item"
      @delEvent="delFn"
    >
    </test>
  </div>
</template>

<script>
import test from "./components/test.vue";
// import vue from "vue";
// vue.component("test", test);
export default {
  components: {
    test,
  },
  data() {
    return {
      arr: [1, 23, 4, 324, 5421, 23421, 24, 234, 24, 42],
    };
  },
  methods: {
    //8.在这里定义delFn方法
    delFn(min) {
      //9.在这里操作数组
      this.arr.splice(
        this.arr.findIndex((item) => item === min),
        1
      );
    },
  },
};
</script>

<style>
</style>

子组件:

<template>
  <div>
    <!-- 3.渲染val值在DOM中 -->
    <span>{{ val }}</span>
    <!-- 4.点击按钮触发btn()方法,并传参val -->
    <button @click="btn(val)">delete</button>
  </div>
</template>

<script>
export default {
  //2.子组件接收到值val
  props: ["val"],
  methods: {
    //5.在此处定义btn()方法
    btn(who) {
      //6.利用this.$emit()方法将自定义事件名,与val值传递出去
      this.$emit("delEvent", who);
    },
  },
};
</script>

<style>
</style>

这样就可以完成一个简单的删除功能,一般删除的话需要传id值,这里就简单使用原值代替一下


思考(有答案可以写在评论区哦)

为什么vue组件的data是个函数呢?

有答案的小伙伴欢迎评论区哦,答案在下期揭晓,未完待续...

上一篇:1 数据降维


下一篇:vue父子页面写法及传值