Component 的 Component (不是递回)

这一篇单纯的介绍几个,重要又常被忽略的 Vue API

在 component 里又再包一个 component 最麻烦的就是将外部的 props 接到内部 component 的 props。

  • user-form
    • user-profile
    • account

假设有一个 <user-form> 里面,包了两个 component。

  • <user-profile> 基本资料
  • <account> 帐号密码
<user-form
  class="float-right"
  enctype="multipart/form-data"
  data-any="lorem_string"
  :name="user.name"
  :account="user.account"
  @submit="onSubmit"
></user-form>

一对一接线 (手动栏位对接)

一开始,就依照基本的语法接线,除了辛苦一点之外,没有其它要考虑的问题

<template>
  <form id="user-form" @submit.prevent="$emit('submit')">
    <user-profile
      :name="name"
    ></user-profile>
    <account
      :account="account"
    ></account>
  </form>
</template>
export default {
 name: 'UserForm',
 prop: {
   name: {
     type: 'String',
     required: true
   },
   account: {
     type: 'String',
     required: true
   }
 }
}

这个方法,在栏位很多的情况之下,就要另外想办去了

整束的接线 (自动栏位对接)

其实观察一下 user-form 上面有三个东西。

attribute

  • class="float-right"
  • enctype="multipart/form-data"
  • data-any="lorem_string"

v-binding

缩写: v-bind:name 等同於 :name

  • :name="user.name"
  • :account="user.account"

v-on

缩写: v-on:submit 等同於 @submit

  • @submit="onSubmit"

要怎麽接线到内部 component

三种做法,三个 API 在 component mounted 的时候,可以把它们印出来?

利用三个 API,可以在文件中查到
https://vuejs.org/v2/api/#vm-attrs
https://vuejs.org/v2/api/#vm-props
https://vuejs.org/v2/api/#vm-listeners

  mounted() {
    console.log('$attrs', Object.keys(this.$attrs));
    console.log('$props', Object.keys(this.$props));
    console.log('$listeners', Object.keys(this.$listeners));
  },

印出来的结果如下

this.$attrs // ["enctype", "data-any"]
this.$props // ["name", "account"]
this.$listeners // ["submit"]

可以透过它们知道,目前 (这个 component) 自己身上有没有 attribite 字串(用 $attrs),有没有 bind 变数($props),有没有 on 行为 ($listeners)

而且,这三个物件都将外部提供的资讯都放好了。
如果不想要像上面的麻烦接线方式,一个栏位一个栏位的接上去。就要知道怎麽样一整束的将东西绑上去。

<component
  v-bind="$attrs"
  v-on="$listeners"
></component>

用在这个例子,会像下面这样。

<template>
  <form id="user-form" @submit.prevent="$emit('submit')">
    <user-profile
      v-bind="$attrs"
      v-on="$listeners"
    ></user-profile>
    <account
      v-bind="$attrs"
      v-on="$listeners"
    ></account>
  </form>
</template>

出错了

检查一下,因为 name 和 account 并不是 UserForm 这个 component 会用到的 props ,所以不需要在它的 component 设定成 props。

因为一但设定了 props ,它就会从 attrs 移到 props

拒绝不必要的接线到内部 component

这样一来,还有一个问题,整束的 $attrs 连接到子 component 时,会出现不必要的属性 在 html 上面,虽然不会有什麽运作上的问题,但是对於团队运作,会产生不必要的沟通成本 (因为不知道哪些有用,还要看 source code)

enctype="multipart/form-data" 还有 data-any="lorem_string" 都从 UserForm 跑到它拥有的所有子 component 了。

<div data-v-2268f1e9="" enctype="multipart/form-data" data-any="lorem_string" name="chris" account="[email protected]" class="float-right">
  <form data-v-2268f1e9="" id="user-form">
    <div data-v-6ef6ca5e="" data-v-2268f1e9="" enctype="multipart/form-data" data-any="lorem_string" account="[email protected]">
      <pre data-v-6ef6ca5e="">
        chris
      </pre>
    </div>
    <div data-v-6d0444a6="" data-v-2268f1e9="" enctype="multipart/form-data" data-any="lorem_string" name="chris">
      <pre data-v-6d0444a6="">
        [email protected]
      </pre>
    </div>
  </form>
</div>

只要在子 component 中使用 inheritAttrs: false 就可以避免不必要的 attrs 跑过去罗。

这招是 titangene 教我的!

export default {
  name: 'UserProfile',
  inheritAttrs: false,
  props: {
    name: {
      type: String,
      required: true,
    },
  },
};
export default {
  name: 'Account',
  inheritAttrs: false,
  props: {
    account: {
      type: String,
      required: true,
    },
  },
};

设定好之後,再执行一次

<div data-v-2268f1e9="" enctype="multipart/form-data" data-any="lorem_string" name="chris" account="[email protected]" class="float-right">
  <form data-v-2268f1e9="" id="user-form">
    <div data-v-6ef6ca5e="" data-v-2268f1e9="">
      <pre data-v-6ef6ca5e="">
        chris
      </pre>
    </div>
    <div data-v-6d0444a6="" data-v-2268f1e9="">
      <pre data-v-6d0444a6="">
        [email protected]
      </pre>
    </div>
  </form>
</div>

这样有比较认识这三个 API 了吗?
一定要先认识哦!超级重要!


<<:  Day20 - 铁人付外挂设定介面(二)- 全域设定

>>:  认识与建立CSS样式表(DAY7)

【学习笔记-CSS】background 各属性

CSS-background各属性 共用的css 写在最上面 body { margin: 0; b...

Electron/Nginx/NodeJS/MongoDB开发HIS之架构概述

前言 今年已经2021相信不少人都已经听说过electron了 小弟技术不才,希望可以给台湾医疗资讯...

[Day06] CH04:我已读你的已读——认识 Scanner

今天我们要来实作一道题目,是不是很期待呢? Question:输入两个数字,印出两数字的和 看到「和...

【Day24】人力资源篇-Time Off

#odoo #开源系统 #数位赋能 #E化自主 休假管理,在实务上又是另一门高深的学问。公司除了必须...

增加 App 下载量必备的 ASO 工具

场景与需求 APP跟网页一样,要被下载,最容易的办法就是要取得流量大的关键字的上位排名,也就是要做S...