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

时间:2014-05-22 18:31:47

标签: vue.js

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

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

4 个答案:

答案 0 :(得分:29)

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

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

您想拥有可重复使用的HTML吗?即可重复使用的小部件?然后使用一个组件。您是否希望其中两个小部件具有离散数据?然后使用一个组件。一个人的数据 NOT 会覆盖另一个人的数据。也许在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>

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

<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>

这里有相当数量的代码。发生的事情是我们正在设置父组件,在父组件内部我们有两个下拉列表。换句话说,下拉组件被调用两次。我试图在显示此代码时提出的观点是:当您单击下拉列表时,该isOpen的{​​{1}}仅对该指令和该指令进行更改。单击其中一个下拉列表不会以任何方式影响其他下拉列表。

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

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

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

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

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

v-for

语法必须是这样的:

<a v-for="link in links" :href="link.href">link.anchor</a>

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

答案 1 :(得分:6)

我这样想:

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

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

答案 2 :(得分:0)

可重用性是使用指令的原因,

虽然组件也在创建可重复使用的小部件,但同一个html系统中的两个组件会覆盖之前的数据&#39;数据&#39;所以在这种情况下请考虑指令。< / p>

值得思考的另一点是 - 用户是否可以在经过一些指示之后通过HTML使用它?

答案 3 :(得分:0)

我认为可以通过两个示例更好地解释这种差异。

  • 组件:是最需要您在某些东西上插入(或添加)自己的HTML标签以进行渲染的包装器。例如。小部件,自定义按钮等,您需要在其中添加一些HTML标记以正确显示它。

  • 指令::不添加标记,而是直接访问HTML标记(已在其中添加了指令)。这使您可以直接修改HTML元素的属性。例如。初始化工具提示,设置CSS样式,绑定到事件等。