vue组件及父子间的通讯

199 阅读5分钟

vue组件化开发

组件是可复用的 Vue 实例, 封装标签, 样式和JS代码

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

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

使用步骤:1.定义组件 2.引入组件 3.注册组件 4.使用组件

口诀: 哪部分标签复用, 就把哪部分封装到组件内

  • 组件内template只能有一个根标签
  • 组件内data必须是一个函数, 独立作用域

基本使用方法:

局部注册组件

  1. 创建组件: MyCom.vue
  2. 引入并注册组件
// 进入到当前组件内部
// 1. 导入组件
import 组件名 from './组件文件.vue'// 2. 局部注册
export default {
   components: {
     组件名,  // es6新语法,属性名与变量名一致时,可简写成一个
   }
}

3.使用组件。在当前页面中,当做标签来使用。

注意:组件名不能与现有的html标签名一致

全局注册组件

全局入口在main.js, 在new Vue之上注册

语法:

import Vue from 'vue'
import 组件对象 from 'vue文件路径'Vue.component("组件名", 组件对象)

main.js

// 全局注册 (一处定义到处使用)
// 1. 创建组件 - 文件名.vue
// 2. 引入组件
import MyCom from './components/MyCom'
// 3. 全局 - 注册组件
/*
  语法: 
  Vue.component("组件名", 组件对象)
*/
Vue.component("MyCom", MyCom)

全局注册MyCom组件名后, 就可以当做标签在任意Vue文件中template里用

单双标签都可以或者小写加-形式, 运行后, 会把这个自定义标签当做组件解析, 使用组件里封装的标签替换到这个位置

<MyCom></MyCom>
</MyCom>
<my-com></my-com>

scoped实现组件的私有样式

解决多个组件样式名相同, 冲突问题

默认组件style 中定义的样式是全局=>存在相同名字覆盖的情况,可通过在style标签上加上scoped属性解决

<stype scoped>
......
// 样式只会在当前组件内生效
</style>
原理
  • 在style上加入scoped属性, 就会在此组件的标签上加上一个随机生成的data-v开头的属性
  • 而且必须是当前组件的元素或者子组件的根元素, 才会有这个自定义属性

image.png 加了scoped的组件,标签自动添加了一个随机生成的data-v开头的属性,组件之间的这个属性值不同

image.png style中,vue帮我们自动变成了属性选择器,只有带有这个属性值的才会被选中,实现了样式的私有化

/deep/深度作用选择符

当父子组件都使用了scoped的情况下,如何在父组件中控制子组件的样式?

父组件的选择器 /deep/ 子组件的选择器

div /deep/ button {
  color: pink;
}

加了 /deep/后,会变为后代选择器,因为子组件也有父组件的data-v-hash属性,所以可以选中进行覆盖,添加

image.png

vue组件通信_父传子

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

  1. 子组件 - props - 变量 (准备接收)

  2. 父组件 - 传值进去

    示意图:

image.png 组件封装复用的标签和样式, 而具体数据要靠外面传入

单向数据流-不要修改props

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

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

原因: 子组件修改, 不通知父级, 造成数据不一致性

所以: Vue规定props里的变量, 本身是只读的

特殊说明:

父组件传给子组件的是一个对象,子组件修改对象的属性,是不会报错的,对象是引用类型, 互相更新;但不能改变引用地址

vue组件通信_子传父

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

语法

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

示意图:

image.png 总结:自定义事件 + $emit

附面试点:

1.请说下封装 vue 组件的过程

首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。

  • 分析需求:确定业务需求,把页面中可以复用的结构,样式以及功能,单独抽离成一个组件,实现复用
  • 具体步骤:Vue.component 或者在new Vue配置项components中, 定义组件名, 可以在props中接受给组件传的参数和值,子组件修改好数据后,想把数据传递给父组件。可以采用$emit方法。
2. Vue组件如何进行传值的

父向子 -> props定义变量 -> 父在使用组件用属性给props变量传值

子向父 -> $emit触发父的事件 -> 父在使用组件用@自定义事件名=父的方法 (子把值带出来)

3.Vue 组件 data 为什么必须是函数

每个组件都是 Vue 的实例, 为了独立作用域, 不让变量污染别人的变量

4. 讲一下组件的命名规范

给组件命名有两种方式(在Vue.Component/components时),一种是使用链式命名"my-component",一种是使用大驼峰命名"MyComponent",

因为要遵循W3C规范中的自定义组件名 (字母全小写且必须包含一个连字符),避免和当前以及未来的 HTML 元素相冲突