Vue 开发人员必须知道的 8 个秘密

2025-05-28

Vue 开发人员必须知道的 8 个秘密


内联语句处理程序:处理多个参数

简短解释:

在内联语句处理程序中,除了$event特殊变量之外,我们还可以访问另一个特殊变量:arguments$event只能访问第一个参数,而arguments可以访问所有参数。

详细说明:

在内联语句处理程序中,我们已经知道我们可以访问特殊$event变量。

因此,如果子组件发出带有参数的事件,我们可以使用以下方式访问它$event

父组件

<template>
  // ...
   <Child @event="someVariable = $event" />
  // ...
</template>
Enter fullscreen mode Exit fullscreen mode

子组件

export default {
  //...
    emitEvent () {
      this.$emit('event', 'a simple text')
    }
  //...
}
Enter fullscreen mode Exit fullscreen mode

当子组件是我们可以访问的组件时,这种方法非常有效,因为我们可以确保只传递一个参数。

但是如果我们使用第三方组件/库(例如 dropzone.js)通过事件传递许多参数怎么办?

只能$event访问第一个参数。请参阅 codesandbox 示例,其中说明了$event只能捕获第一个参数。(单击按钮即可查看控制台

在这种情况下,$event我们可以使用arguments,并且所有参数都可以访问。

因此,在上面的代码中,为了使其工作,我们必须将第 4 行更改为Child.vue

从:

<GrandChild @event="$emit('event', $event)"/> 
Enter fullscreen mode Exit fullscreen mode

到:

 <GrandChild @event="$emit('event', arguments)"/>
Enter fullscreen mode Exit fullscreen mode

从功能组件发出事件

简短解释:

使用函数式组件意味着我们无法访问this上下文。因此,我们无法执行this.$emit()。但是……我们可以访问 ,listeners所以我们可以执行<button @click="listeners.clicked"></button>

详细说明:

函数式组件是无状态的(没有响应式数据)和无实例的(没有 this 上下文)。但是函数式组件可以访问一些属性,例如propschildren等等,以及最重要的(在本例中)listeners

根据Vue 文档
listeners:包含父级注册的事件监听器的对象。这是 data.on 的别名。

这意味着我们可以从功能组件发出事件。Wiii :P

简单示例:

<template functional>
  <button @click="listeners['custom-event']('message from child')">
    Button from child
  </button>
</template>
Enter fullscreen mode Exit fullscreen mode

工作示例单击按钮并打开控制台

如果我们想从带有渲染函数的函数组件中发出事件,该怎么办?可以吗?当然可以!

简单示例:

export default {
  functional: true,
  render(createElement, { listeners }) {
    return createElement(
      "button",
      {
        on: {
          click: event => {
            const emit_event = listeners.event_from_child;
            emit_event("Hello World!Is this the message we excpected? :/");
          }
        }
      },
      "Pass event to parent"
    );
  }
};
Enter fullscreen mode Exit fullscreen mode

工作示例

有人可能会问,我们能不能用这种方法来使用.syncModifier
? 答案是?当然!

<button @click="listeners['update:message']('some text')">Click me</button>
Enter fullscreen mode Exit fullscreen mode

将所有 props 传递给子组件

假设我们有一个组件,它接收参数props,并且我们想将所有这些 props 传递给子组件。为了实现这一点,我们可以这样做:

  <ChildComponent v-bind="$props" />
Enter fullscreen mode Exit fullscreen mode

利用v-bind我们还可以拥有如下对象:

data: () =>({
  obj: {
    firstName: 'John',
    lastName: 'Doe',
    age: 30
  }
})
Enter fullscreen mode Exit fullscreen mode

并将firstNamelastNameage作为props子组件传递,例如:

<Child v-bind="obj" />
Enter fullscreen mode Exit fullscreen mode

从父级观察子级属性的变化

你可能想知道为什么要这么做,你是对的!这是一种不好的做法。但有时你会使用第三方组件,并且希望监视它们的属性以满足你的需求。

很久以前,在一个项目中,我们使用了一个日期选择器,我们希望能够检测弹出窗口何时可见。可惜的是,没有这个选项。我发现日期选择器使用了一个popupVisible响应式属性,但库没有公开它。所以我不得不想办法从我的组件中监控这个属性。

下面的代码无法检测变化:

  watch: {
    '$refs.datePicker.popupVisible': {
      handler (new_value) {
        console.log('value changed')
      },
      deep: true
    }
  }
Enter fullscreen mode Exit fullscreen mode

为了检测子组件属性的变化,您应该执行以下操作:

  mounted() {
    this.$watch(
      "$refs.picker.popupVisible",
      (new_value, old_value) => {
         //execute your code here
      }
    );
  }
Enter fullscreen mode Exit fullscreen mode

工作示例:

详细了解vm.$watch


在路由器视图中监听子事件

大多数人应该已经知道这一点,因为它很简单,但我已经被问过很多次下面的问题了。

假设你有一个具有嵌套路由的组件:

<template>
  //...
  <router-view></router-view>
  //...
</template>
Enter fullscreen mode Exit fullscreen mode

并且您有如下嵌套路线:

<template>
  //...
  <button @click="$emit('event')"></button>
  //...
</template>
Enter fullscreen mode Exit fullscreen mode

因此,与嵌套路由对应的组件会发出一个事件。问题是:如何监听该事件?

简单的答案用代码演示:

<template>
  //...
  <router-view @event="callAMethod"></router-view>
  //...
</template>
Enter fullscreen mode Exit fullscreen mode

router-view没错!我们在组件中监听该事件


Vue 组件生命周期钩子并不按照你认为的顺序运行

假设您有 2 个页面。主页和关于。

当从主页切换到关于时,关于组件的钩子将在主页组件的钩子之前运行createdbeforeDestroy稍等片刻

奇怪吗?尝试通过查看控制台在下面的工作示例中切换路线。

作为解决方案(虽然我不知道这是否是最好的解决方案),您可以使用transition-mode out-in

    <transition mode="out-in">
      <router-view></router-view>
    </transition>
Enter fullscreen mode Exit fullscreen mode

如何知道子组件是否已安装?

这是我在这里读到的最喜欢的技巧之一(Vue Dose)

假设你有一个子组件,并且你想在子组件的钩子执行时执行某些操作。你可以这样做:

<Child @hook:created="doSomething" />
Enter fullscreen mode Exit fullscreen mode

因此,如何知道子组件何时安装的问题是:

<Child @hook:mounted="componentMountedDoSomething" />
Enter fullscreen mode Exit fullscreen mode

如何知道动态 vuex 注册的模块是否已注册?

借助动态注册/注销vuex 模块的功能,我们可以大大提高性能。

推荐大家阅读一篇非常有用的文章:性能优化:延迟加载 vuex 模块

我们可以注册一个 vuex 模块:

this.$store.registerModule('my-module', MyModule)

并取消注册:

this.$store.unregisterModule('my-module')

要知道模块是否已经注册:

if (Object.keys(this.$store._modules.root._children).includes('my-module')) {
        // module is registered
}
Enter fullscreen mode Exit fullscreen mode

我的时间非常有限,但我很高兴能抽出时间来写这篇文章(虽然花了不少时间)。希望它能对你有所帮助,也希望你喜欢。

如果您能留言提供解决方案,我将非常高兴。例如,关于最后一个“秘密”,您可以使用 Vuex Store 来指示模块是否已注册。

这是我在DEV 社区的第一篇文章。感谢阅读。

文章来源:https://dev.to/the_one/8-secrets-vue-developers-must-know-5la
PREV
使用 Github Actions 像专业人士一样部署到 Github Pages
NEXT
Docker 精通:面向初学者和专业人士的综合指南