简体   繁体   English

一个带有多个模板的 VueJS 组件

[英]One VueJS Component with multiple templates

How can I have a component with multiple templates or otherwise separate any methods and data away from any one specific template?如何让一个组件具有多个模板或以其他方式将任何方法和数据与任何一个特定模板分开?

Components in VueJS are supposed to be a reusable piece, aren't they? VueJS 中的组件应该是可重用的,不是吗? If I have a user with its methods and data, surely it will behave the same throughout most (all?) of my UI.如果我有一个拥有它的方法和数据的用户,它肯定会在我的大部分(全部?)UI 中表现相同。 However, the way it will be displayed will vary.但是,它的显示方式会有所不同。

I often accomplish this by passing in a prop and using that prop for conditional rendering.我经常通过传入一个道具并使用该道具进行条件渲染来实现这一点。

For example:例如:

<template>
    <div>
        <div v-if="isActive">RADICAL ACTIVE STATE</div>
        <div v-if="!isActive">YOLO NOT ACTIVE</div>
    </div>
<template>

<script>
export default {
    props: {
        isActive: {
            type: Boolean,
            required: true,
        },
    },
};
</script>

That will probably get you there 80% of the time unless that "single root wrapper" thing is causing you a problem.除非那个“单根包装器”的东西给你带来了问题,否则这可能会让你有 80% 的时间到达那里。

In that case, you definitely have options.在这种情况下,你肯定有选择。 One of which could be to use a slot and control the conditional rendering upstream.其中之一可能是使用插槽并控制上游的条件渲染。 That might result in less markup.这可能会导致标记减少。

Maybe you could instead just create two components that are each simpler than they would be otherwise.也许您可以改为创建两个组件,每个组件都比其他组件更简单。 Reducing cyclomatic complexity is always good.降低圈复杂度总是好的。

You can also throw v-if on the template itself <template v-if=""> .你也可以在模板本身上抛出 v-if <template v-if="">

In my experience today, you cannot use two templates in one single file component (like the one in the code I showed above).根据我今天的经验,您不能在一个文件组件中使用两个模板(就像我上面展示的代码中的那个)。 Vue doesn't seem to parse the templates correctly. Vue 似乎没有正确解析模板。 Vue was simply not executing my computed prop or method. Vue 根本没有执行我的计算道具或方法。 It was always rendering the second template, so Vue may have internal logic whereby it loads the "last observed template".它总是渲染第二个模板,所以 Vue 可能有内部逻辑,它加载“最后观察到的模板”。

A person will probably find it helpful to read http://vuejs.org/guide/components.html#Fragment_Instance because it illustrates the template instance prop.人们可能会发现阅读http://vuejs.org/guide/components.html#Fragment_Instance很有帮助,因为它说明了template实例道具。

It's the closest I've seen to the React equivalent to a stateless dumb component such as:这是我见过的最接近 React 的等效于无状态愚蠢组件的组件,例如:

const ShowNumber = ({ num }) => (
    <div>{num}</div>
)

...

<ShowNumber num={1337} />

If my answer here is wetting your appetite but you feel like it still isn't quite what you need, Google "Vue render props" and take a look at how you can do crazy-complex logic inside the render instance prop.如果我在这里的回答满​​足了你的胃口,但你觉得它仍然不是你所需要的,谷歌“Vue 渲染道具”并看看你如何在render实例道具中执行疯狂复杂的逻辑。 It's very similar to React's JSX, but I will say that if you are in this territory, there is probably a simpler way to do it.它与 React 的 JSX 非常相似,但我会说,如果你在这个领域,可能有更简单的方法来做到这一点。

I might recommend just creating two single-file components with one template in each, or find a way to use slots and control the behaviour from upstream.我可能会建议只创建两个单文件组件,每个组件都有一个模板,或者找到一种方法来使用插槽并控制上游的行为。

You are also pretty safe to do it like I showed in my example above, because the data flow through the component is unidirectional and deterministic, and the UI will always be a reflection of the props and data.您也可以像我在上面的示例中展示的那样非常安全地执行此操作,因为通过组件的数据流是单向和确定性的,并且 UI 将始终是道具和数据的反映。 If the props or data change, your component will render the correct elements.如果道具或数据发生变化,您的组件将呈现正确的元素。

You could do this in the upstream parent component:您可以在上游父组件中执行此操作:

<large-widget v-if="someState === 'one'"></large-widget>

<small-widget v-else-if="someState === 'two'"></small-widget>

<div v-else>WIDGET IS BORKEN</div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM