From 83d175abc6932bf9a67b62b7bd9f965418e45353 Mon Sep 17 00:00:00 2001 From: Justineo Date: Thu, 24 Oct 2024 11:15:22 +0800 Subject: [PATCH] feat: `v-skip` directive --- active-rfcs/0000-v-skip.md | 183 +++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 active-rfcs/0000-v-skip.md diff --git a/active-rfcs/0000-v-skip.md b/active-rfcs/0000-v-skip.md new file mode 100644 index 00000000..48cf9a56 --- /dev/null +++ b/active-rfcs/0000-v-skip.md @@ -0,0 +1,183 @@ +- Start Date: 2024-10-24 +- Target Major Version: 3.x +- Reference Issues: (fill in existing related issues, if any) +- Implementation PR: (leave this empty) + +# Summary + +This RFC proposes the addition of a new directive, `v-skip`. The `v-skip` directive conditionally skips rendering the current element or component while preserving and promoting its child nodes to the parent level in the node hierarchy. This behavior differs from `v-if`, which entirely removes the node and its subtree when the condition is `false`. + +# Basic example + +```vue + +``` + +# Motivation + +There are scenarios where developers need to conditionally remove an element or component without discarding its children. Currently, achieving this requires workarounds such as using userland components or switching to render functions, which can be verbose and less intuitive. + +Related: + +- https://github.com/vuejs/vue/issues/12033 + + This issue discussed the need of a conditional wrapper. The workaround (bare basic, not robust) provided in [one comments](https://github.com/vuejs/vue/issues/12033#issuecomment-1183981371) is: + + ```vue + + + + ``` + + There was also a [comment](https://github.com/vuejs/vue/issues/12033#issuecomment-1167564997) proposing a `v-wrap-if` directive: + + ```vue +
+ + This is a span that is sometimes wrapped up in a div. + +
+ ``` + +- https://github.com/vuejs/rfcs/pull/449 + + This RFC propsed a built-in `fragment` component to make utilizing conditional wrappers easier. + + ```vue + + ``` + +- https://dev.to/alexander-nenashev/creating-a-conditional-wrap-component-in-vue-3-18ml + + This post series introduced a way to implement a conditional wrapper component which is quite cumbersome and relied on some knowledge of Vue's internals. The usage of the component is also not as concise as a directive. + +The userland component is quite hard to be implemented correctly and when it comes to toggling a component and passing through its props, slots and event listeners, it becomes verbose to use as well. It becomes even harder if we want correct type support. + +The `v-skip` directive aims to provide a more concise and declarative approach to tackle this problem. It eliminates the need for userland components, eases the pain of passing props + or switching to render functions, and makes the code more readable and maintainable. + +# Detailed design + +The `v-skip` directive accepts an expression that evaluates to a boolean value. + +## For elements + +```vue +
+

Hello

+
+``` + +- If `condition` is truthy, the current node is skipped, and its children are rendered in its place (render as if it's a fragment node) and produces: + + ```vue +

Hello

+ ``` + +- Otherwise, the node and its children are rendered normally and produces: + + ```html +
+

Hello

+
+ ``` + +## For components + +Let's say we have a `Tooltip` component which is used like this: + +```vue + + + + +``` + +Which renders: + +```html +
+ +
+ The button is disabled because ... +
+
+``` + +We can conditionally skip the `Tooltip` component like this: + +```vue + + + + +``` + +- If `disabled` is falsy (`v-skip` evaluates to `true`), the `Tooltip` component is skipped, we directly render its `default` slot in its place and discard other slots, which produces: + +```html + +``` + +## Implementation details + +- The children of the node with `v-skip` directive should be rerendered when the condition changes as the their parent may have provided contextual data (`provide`, etc.). +- `v-skip` cannot be used on `