组件通讯

192 阅读3分钟

什么是组件化开发

组件化开发 :一个页面(.vue)可能有一个或多个组件(.vue)组成完整的页面功能。

  • 封装的思想,把页面上 可重用的部分 封装为 组件,从而方便项目的 开发 和 维护。

一个页面, 可以拆分成一个个组件,一个组件就是一个整体, 每个组件可以有自己独立的 结构(template) 样式(style) 和 行为(script) (html, css和js)

image.png

vue组件-用scoped实现组件的私有样式

默认组件style 中定义的样式是全局样式,会把其他组件中的标签也设置上样式,存在相同名字覆盖的情况。

image.png 解决方案:
局部样式:在style标签上加上[scoped属性]

<stype scoped> //加scoped, 组件内的样式只在当前vue组件生效;相反如果不加,样式就是全局的
  h2 {} // h2样式只会在当前组件内生效
</style>
  • 在style上加入scoped属性, 就会在此组件的标签上加上一个随机生成的data-v开头的属性。
  • 而且必须是当前组件的元素或者子组件的根元素, 才会有这个自定义属性。

vue组件-/deep/深度作用选择符

当父子组件都使用了scoped之后,使用/deep/可以在父组件中控制子组件中的样式。

div /deep/ button{ //在父组件style中,设置button样式加上/deep/,就可以控制子组件button元素的样式
    background-color: pink;
  }
  • 父组件中控制子组件元素或类名,覆盖样式=》需要在前边加上 /deep/
  • 注意⚠️:默认子组件的根元素,会带上父组件的data-v-hash属性,所以可以直接控制。

vue组件通讯_父传子

如果一个组件A在组件B中被导入使用,称组件B是父组件,组件A是子组件。
格式

父组件中:< 子组件 @自定义事件名1="父methods函数1" @自定义事件名2="父methods函数2" />

image.png

父传子组件通讯,需要先在父组件中自定义一个动态属性,然后将这个自定义的属性在子组件中使用props属性接收。 父组件:

<template>
  <div style="border:1px solid #ccc;margin:5px">
    <h1>我是父组件</h1>
        <!-- 父传自定义属性 -->
    <MyCom :abc='userName' :list="hobby"/>
  </div>
</template>

<script>
import  MyCom from './MyCom.vue' //导入文件路径
export default {
  data(){
  //要传送给子组件的数据
    return{
     userName:'小白',
     hobby:['vue','js']
    }
   
  },
  components:{MyCom} //注册组件 
}
</script>

注意:

  • 加冒号: 后面是vue变量数据。
  • 不加冒号: 后面认为是字符串。 子组件
<template>
  <div style="border:1px solid #ccc;margin:5px" >
    <h1>我是子组件</h1>
    <!-- 使用插值表达式 -->
    {{abc}}
    <p>{{list[1]}}</p>
    <button @click="fn">打印</button>
  </div>
</template>

<script>
export default {
  props:['abc','list'],//使用props属性接收父组件自定义的属性名
  methods: {
    fn(){
      console.log(this,this.abc); //控制台会打印出小白
    }
  },
}
</script>

vue单向数据流

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

  1. 在父传子的前提下,父组件的数据发生会通知子组件自动更新。
  2. 子组件内部,不能直接修改父组件传递过来的props => props是只读的。

image.png 不要在子组件内部,修改父组件的数据。

说明:父组件传给子组件的是一个对象,子组件修改对象的属性,是不会报错的,对象是引用类型, 互相更新;但不能改变引用地址 props的值不能重新赋值, 但是引用类型可以子改父。

vue组件通信_子传父

子传父是指:从子组件内部把数据传出来给父组件使用或者修改父组件数据

子组件: this.$emit("自定义事件名1", 传值1) ---> 执行父methods里函数代码

父组件

<template>
  <div style="border:1px solid #ccc; margin:5px;padding:5px">
    <h1>子传父</h1>
     添加事件监听
    <MyCom @abc="fn"/>  当子组件发生了abc事件要执行fn函数,将数据传送到fn的参数里
      <button>改数据</button>
  </div>
</template>

<script>
// 导入
import MyCom from './MyCom.vue'
export default {
  components: { MyCom },
  
 methods: {
   fn(obj){                           //参数接收传递来的数据
     console.log('fn子组件',obj);
   }
 },
}
</script>

子组件

<template>
  <div style="border:1px solid #ccc; margin:5px;padding:5px">
    <h2>子组件</h2>
    <button @click="fn">触发abc事件</button> //点击按钮将数据传送到父组件中
  </div>
</template>

<script>
export default {
  methods: {
    fn(){
      console.log('子组件click')
      // 2. 触发abc事件
      this.$emit('abc',{name:'小花'}) //使用$emit属性传数据
    }
  }
}
</script>

总结

  • scoped属性可以实现组件的私有样式。使组件内的样式只在当前vue组件内生效。
  • /deep/ 可以在父组件中控制子组件中的样式。
  • 父传子语法: 父组件中:< 子组件 @自定义事件名1="父methods函数1" @自定义事件名2="父methods函数2" />
    子组件接收:props:['父组件中自定义的事件名','']
    props的值不能重新赋值, 但是引用类型可以子改父
  • 子传父语法: 子组件: this.$emit("自定义事件名1", 传值1) ---> 执行父methods里函数代码
    父组件接收:@自定义事件名="methods函数" 里面的参数用来接收传来的数据