组件间的数据传递

179 阅读4分钟

单向数据流

数据只能通过父组件传递给子组件 而不能从子组件传递给父组件 子组件也不能直接修改父组件的数据

  • 当父组件的数据发生改变之后,子组件的收到的数据也会跟着变化
  • 子组件想修改父组件的数据,只能通知父组件,让父组件修改数据

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <son :msg="pmsg"></son>
</div>

<script src="vue.js"></script>
<script>
  let son = {
    data() {
      return {
        hello: 'xxxx'
      }
    },
    props: ['msg', 'changePMSG'],
    template: '<span>{{msg}} <button @click="fn">dddd</button></span>',
    methods: {
      fn() {
        this.msg = 1233; // props 中的数据也会代理到子组件的实例身上,可以直接通过 this 访问
      }
    }
  };

  let vm = new Vue({
    el: '#app',
    data: {
      pmsg: 'msg from parent'
    },
    methods: {
      changeMsg() {
        this.pmsg = 123445
      }
    },
    components: {
      son
    }
  });
  // 1. 子组件中的数据不能全是写死的,而是有一部分从父组件传递过来的
  // 2. 为了把父组件的数据传递给子组件,子组件在标签上动态绑定一个属性,这个属性绑定父组件的数据,并且在子组件的props中注册这个属性
  // 3. 子组件如果想使用父组件的数据,就使用对应的 props 就可以(父传子用props)

</script>
</body>
</html>

子传父

  1. 子组件传给父组件通过事件机制 通知父组件 让父组件修改数据
  2. 父组件中使用子组件时 要监听一个自定义的事件事件名不能写驼峰 如@change-msg=modify
  3. 子组件若想修改某个数据时 调用 this.$emit(事件名,数据)
  4. 子组件 emit后 父组件收到这个事件会执行事件绑定的方法 方法的形参 可以接收子组件emit的数据
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="app">
  <son :pmsg="msg" @change-msg="modify"></son>
</div>

<script src="vue.js"></script>
<script>
  let son = {
    data() {
      return {
        msg: '123'
      }
    },
    template: `<div>{{pmsg}} <button @click="fn">修改</button></div>`,
    props: ['pmsg'],
    methods: {
      fn() {
        this.$emit('change-msg', '12345上山打老虎');
      }
    }
  };

  let vm = new Vue({
    el: '#app',
    data: {
      msg: 'msg from parent'
    },
    methods: {
      modify(val) {
        // console.log(val);
        this.msg = val;
      }
    },
    components: {
      son
    }
  });
</script>

</body>
</html>

props验证

props属性除了设置为一个数组还可以设置一个对象 key 是props名 值 是一个对象 在这个对象中可以设置默认值 以及对这个props的校验规则

常见的校验

  • type:Number //校验类型 要求必须是某种类型 若类型不对会抛出警告
  • required:true //必传校验 若不传会引发警告
  • default:111 //设置默认值
  • validator(val){} //验证器函数 若有问题可以抛出异常 没问题要return true

sync修饰符 和事件简写

sync修饰符 为了简化子传父

sync 使用

  • 父组件在使用子组件时 在prop后面增加.sync修饰符 取消监听事件
  • 子组件触发事件时 事件名写update:prop 属性名 父子组件都有mounted 先执行子组件的mounted 再执行父组件的mounted

动态组件 不同组件之间的动态切换

需要使用内置的component组件 组件上有一个is属性 动态绑定该属性 当被绑定的值发生变化时 Vue会渲染is嘴子女的值对应的组件

keep-alive 解决在组件切换时 原来的组件会销毁 数据会丢失

包裹动态组件时 会缓存不活动的组件实例 而不是销毁它们

事件总线 EventBus

每个组件都是一个Vue实例 相互之间不能互通数据 要修改数据一定要通知 因此找一个第三方监听事件 在事件触发时执行对应的修改数据的操作 这个第三方就是事件总线

用法

  1. 创建一个空的Vue实例 let EventBus = new Vue()
  2. eventBus.$on(自定义事件名,事件函数) 监听事件
  3. eventBus.$emit(事件名) 触发事件

插槽 slot

使用插槽机制 可以向组件的标签中嵌入内容 这些内容可以嵌入到子组件中

使用

  1. 在创建子组件时 需要声明一个slot标签占位
  2. 在组件标签中嵌入内容

具名slot

在声明时 不写name 属性 嵌入在组件标签中没有写slot属性的标签都会放在匿名的slot中

匿名slot

在声明时 要写上name属性 嵌入在组件标签中的内容需要指定slot= “slot的名字”