组件化开发

1.组件化思想

将一个完整的页面分成很多个组件,每个组件都用于实现页面的一个功能块。而每一个组件又可以进行细分,整个页面都将变得容易管理维护。
在这里插入图片描述
组件化是Vue.js中的重要思想
它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
任何的应用都会被抽象成一颗组件树。
在这里插入图片描述
组件化思想的应用:
有了组件化的思想,我们在之后的开发中就要充分的利用它。
尽可能的将页面拆分成一个个小的、可复用的组件。
这样让我们的代码更加方便组织和管理,并且扩展性也更强。

2.注册组件

2.1注册组件的基本步骤

组件的使用分成三个步骤:

  1. 创建组件构造器
  2. 注册组件
  3. 使用组件。

在这里插入图片描述

2.2注册组件步骤解析

1.Vue.extend():
调用Vue.extend()创建的是一个组件构造器。
通常在创建组件构造器时,传入template代表我们自定义组件的模板。
该模板就是在使用到组件的地方,要显示的HTML代码。
事实上,这种写法现在几乎已经看不到了,它会直接使用语法糖。

2.Vue.component():
调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。
所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

3.组件必须挂载在某个Vue实例下,否则它不会生效。
如上图,实际使用了两次,而第二次其实并没有生效

在这里插入图片描述

2.3组件的其他补充

**

1.全局组件和局部组件

**

  • 调用Vue.component()注册组件时,组件的注册是全局的 这意味着该组件可以在任意Vue示例下使用。

在这里插入图片描述

  • 如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件
    在这里插入图片描述
    **
2.父组件和子组件

**
组件和组件之间存在层级关系,而其中一种非常重要的关系就是父子组件的关系
在这里插入图片描述

3.注册组件语法糖

注册组件的方式,有些繁琐。Vue为了简化这个过程,提供了注册的语法糖。主要是省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替。
在这里插入图片描述
在这里插入图片描述

4.模板的分离写法

将其中的HTML分离出来写,然后挂载到对应的组件上,使结构变得非常清晰

Vue提供了两种方案来定义HTML模块内容:

1.使用<script>标签
<!--1.script标签, 注意:类型必须是text/x-template-->
<script type="text/x-template" id="cpn">
<div>
  <h2>我是标题</h2>
  <p>我是内容,哈哈哈</p>
</div>
</script>
2.使用<script>标签
<template id="cpn">
  <div>
    <h2>我是标题</h2>
    <p>我是内容,呵呵呵</p>
  </div>
</template>

3.父子组件的通信

如何进行父子组件间的通信呢?

  • 通过props向子组件传递数据
  • 通过事件向父组件发送消息
    在这里插入图片描述

3.1父级向子级传递 props

在组件中,使用选项props来声明需要从父级接收到的数据。
props的值有两种方式:
方式一:字符串数组,数组中的字符串就是传递时的名称。
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。
在这里插入图片描述
当需要对props进行类型等验证时,就需要对象写法了。
验证支持的据类型:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol
  • 当我们有自定义构造函数时,验证也支持自定义的类型
<div id="app">
  <cpn :c-info="info" :child-my-message="message" v-bind:class></cpn>
</div>

<template id="cpn">
  <div>
    <h2>{{cInfo}}</h2>
    <h2>{{childMyMessage}}</h2>
  </div>
</template>

<script src="../js/vue.js"></script>
<script>
  const cpn = {
    template: '#cpn',
    props: {
      cInfo: {
        type: Object,
        default() {
          return {}
        }
      },
      childMyMessage: {
        type: String,
        default: ''
      }
    }
  }

  const app = new Vue({
    el: '#app',
    data: {
      info: {
        name: '妍华',
        age: 21,
        height: 1.66
      },
      message: 'aaaaaa'
    },
    components: {
      cpn
    }
  })
</script>

在这里插入图片描述

3.2子级向父级传递 自定义事件

自定义事件的流程:
在子组件中,通过$emit()来触发事件。
在父组件中,通过v-on来监听子组件事件。

在这里插入图片描述

3.3父子组件的访问方式

1.$children
父组件访问子组件:使用$children或$refs

子组件访问父组件:使用$parent

在这里插入图片描述

$children的访问

this.$children是一个数组类型,它包含所有子组件对象。
我们这里通过一个遍历,取出所有子组件的message状态。
$children的缺陷:

通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。
但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。
有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs
2.$refs

$refs的使用:

$refs和ref指令通常是一起使用的。
首先,我们通过ref给某一个子组件绑定一个特定的ID。
其次,通过this.$refs.ID就可以访问到该组件了。

在这里插入图片描述
在这里插入图片描述

3.$parents
在子组件中直接访问父组件,可以通过$parent
注意事项:

尽管在Vue开发中,我们允许通过$parent来访问父组件,但是在真实开发中尽量不要这样做。

子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。

如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。

另外,更不好做的是通过$parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护。

在这里插入图片描述

4.插槽 v-slot

官方文件:https://cn.vuejs.org/v2/guide/components-slots.html

特别注意:在 2.6.0 中,官方为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍在文档中的 attribute。新语法的由来可查阅这份 RFC。

v-slot :后边是插槽名称=后边是组件内部绑定作用域值的映射。

4.1编译作用域

官方给出了一条准则:
父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译

组件的插槽:

  • 组件的插槽也是为了让我们封装的组件更加具有扩展性。
  • 让使用者可以决定组件内部的一些内容到底展示什么。

举例:移动网站中的导航栏

  • 移动开发中,几乎每个页面都有导航栏。
  • 导航栏必然会封装成一个插件,比如nav-bar组件。
  • 一旦有了这个组件,我们就可以在多个页面中复用了。

以京东为例,每个页面的导航并不全然相同
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如何封装呢?抽取共性,保留不同。

  • 最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。
  • 一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。
  • 是搜索框,还是文字,还是菜单。由调用者自己来决定

4.2 具名插槽

在指定的位置输出我们的子元素,这时候具名插槽就排上了用场。该插槽插入什么内容取决于父组件如何使用

在其他组件中使用子组件

<child>
  <template v-slot:slotName>
    hello world
  </template>
</child>

子组件

<div>
  <slot name="slotName"></slot>
</div>

上面是具名插槽的用法,省略插槽名:name属性或插槽名为default表示匿名插槽

4.3插槽作用域

用法一:常规用法,slotProps为自定义作用域名

<child>
  <template v-slot:slotName=“slotProps”>
    hello world
    <span>{{ slotProps.user.firstName }}</span>
  </template>
</child>

用法二:解构插槽Prop,实际上就是ES6解构JSON,可以使用:替换参数名

<child>
  <template v-slot:slotName=“{ user, age:nianling }”>
    hello world
    <span>{{ user.firstName }}</span>
    <span>{{ nianling }}</span>
  </template>
</child>

child组件,定义时将需要使用的作用域数据绑定在<slot>即可,:user="user" :age="age"

<template>
  <div>
    <slot name="slotName" :user="user" :age="age"></slot>
  </div>
</template>

<script>
export default {
  data () {
    return {
      user: {
        firstName: 'Cliff',
        lastName: 'Rhine'
      },
      age: 24
    }
  }
}
</script>

作用域插槽是slot一个比较难理解的点,而且官方文档说的又有点不清晰,其实最好的理解就是:

父组件替换插槽的标签,但是内容由子组件来提供。

在这里插入图片描述
在这里插入图片描述
在上面这个例子中:

在父组件使用我们的子组件时,从子组件中拿到数据:

  • 我们通过获取到slotProps属性
  • 在通过slotProps.data就可以获取到刚才我们传入的data了

(注:部分图片来源见水印 微博:coderwhy)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值