vue.js指令与组件的用例?

Jeh*_*han 18 vue.js

我什么时候应该使用指令vs vue.js中的组件?我正在从Bootstrap实现一些东西,看起来我可以这样做(我从下拉菜单开始).

我觉得指令更多的是用于在单个元素上操作dom,而组件用于打包一堆数据和/或dom操作.这是一个好看的方式吗?

Mar*_*lin 34

此Stack Overflow问题是Google查询"vue directive vs component"的第一个结果.Saurshaz的回答目前是被接受的,在Vue 2.0中是非常错误的.我想这会导致很多人误入歧途,所以我要在这里权衡一下.

"我应该在Vue中使用指令或组件"的答案几乎总是一个组件.

你想拥有可重复使用的HTML吗?即可重复使用的小部件?然后使用一个组件.您是否希望其中两个小部件具有离散数据?然后使用一个组件.一个数据不会覆盖另一个数据.也许在Vue 1.0中也是如此,我不知道.但在Vue 2.0中绝对不是这样.在Vue 2.0中,您的组件具有data返回一组唯一数据的函数.考虑一下Vue下拉列表的真实情况,该下拉列表具有类似于UI Bootstrap下拉列表的HTML标记:

<template>
  <span class="dropdown sm-dropdown" @click="toggle" :class="{'open': isOpen}">
    <a class="dropdown-toggle">
      <span class="special-field">{{ label }}</span>
    </a>
    <ul class="dropdown-menu">
      <li v-for="choice in choices">
        <a @click.prevent="click(choice)">{{ choice.label }}</a>
      </li>
    </ul>
  </span>
</template>

<script>
  export default {
    name: 'Dropdown',
    props: ['label', 'options', 'onChange'],
    data() {
      return {
        choices: this.options,
        isOpen: false
      }
    },
    methods: {
      click(option) {
        this.onChange(option);
      },
      toggle() {
        this.isOpen = !this.isOpen;
      }
    }
  }
</script>
Run Code Online (Sandbox Code Playgroud)

现在在父组件中,我可以这样做:

<template>    
  <div class="container">
    <dropdown
      label="-- Select --"
      :options="ratingChoices"
      :onChange="toggleChoice"
    >
    </dropdown>

    <dropdown
      label="-- Select --"
      :options="ratingChoices"
      :onChange="toggleChoice"
    >
    </dropdown>
  </div>
</template>

<script>
  import Dropdown from '../dropdown/dropdown.component.vue';

  export default {
    name: 'main-directive',
    components: { Dropdown },
    methods: {
      toggleChoice(newChoice) {
        // Save this state to a store, e.g. Vuex
      }
    },
    computed: {
      ratingChoices() {
        return [{
          value: true,
          label: 'Yes'
        }, {
          value: false,
          label: 'No'
        }]
      }
    }
  }
</script>
Run Code Online (Sandbox Code Playgroud)

这里有相当数量的代码.发生的事情是我们正在设置一个父组件,在该父组件内部我们有两个下拉列表.换句话说,下拉组件被调用两次.我想在此显示的代码说明的一点是:当你点击下拉列表中,isOpendropdown改变该指令,并且仅该指令.单击其中一个下拉列表不会以任何方式影响其他下拉列表.

不要根据您是否需要离散数据来选择组件或指令.组件允许离散数据.

那么你什么时候想在Vue中选择一个指令呢?

以下是一些指导方针,希望能让您思考正确的方向.

  • 当您想要扩展HTML组件的功能时,您希望选择一个指令,并且您怀疑在多个组件中需要这种可扩展性,并且您不希望DOM因此而变得更深.为了理解我的意思,让我们看一下Vue提供的开箱即用的指令.以其v-for指令为例.它允许您循环遍历集合.这非常有用,您需要能够在任何您想要的组件中执行此操作,并且您不希望DOM更深入.当指令是更好的选择时,这是一个很好的例子.[1]
  • 如果希望单个HTML标记具有多个功能,则需要选择指令.例如,既触发Ajax请求又具有自定义工具提示的元素.假设您想要在除Ajax触发元素之外的元素上使用工具提示,将它们分成两个不同的东西是有意义的.在这个例子中,我将使工具提示成为一个指令,并由组件驱动Ajax特性,这样我就可以利用@click组件中可用的内置指令.

1 更加好奇的脚注.理论上v-for可以作为一个组件,但这样做每次你想要使用时都需要一个比必要的更深的DOM v-for以及更笨拙的语法.如果Vue选择用它来制作一个组件,而不是这个:

<a v-for="link in links" :href="link.href">link.anchor</a>
Run Code Online (Sandbox Code Playgroud)

语法必须是这样的:

<v-for items="link in links">
  <a :href="link.href">link.anchor</a>
</v-for>
Run Code Online (Sandbox Code Playgroud)

这不仅是笨拙的,而且由于组件代码需要实现<slot></slot>语法才能获得innerHTML,并且因为插槽不能是<template>声明的直接子节点(因为不能保证插槽标记具有单个节点的入口)它的顶级),这意味着组件定义中必须有一个周围的顶级元素v-for.因此DOM会比必要的更深.指令在这里明确是正确的选择.


Dav*_*ess 7

我这样想:

组件定义小部件 - 这些是具有与之关联的行为的html部分.

指令修改html部分的行为(可能是也可能不是小部件).