您的Vue应用程序中是否有共享类似选项或甚至模板标记的组件?
使用通用选项和标记创建基本组件是一个不错的主意,然后扩展基本组件以创建子组件。这样的体系结构将帮助您在代码中应用DRY原则(不要重复自己),这可以使您的代码更具可读性并减少错误发生的可能性。
Vue提供了一些帮助组件继承的功能,但是您还必须添加一些自己的独创性。
例如:调查问题
这是一个使用Vue.js进行的简单调查:
1. 文本输入
2. 选择输入
3. 无线电输入
一个好的架构是将每个问题/输入类型变成一个不同的,可重用的组件。我已经命名它们以符合上述内容:
1. SurveyInputText
2. SurveyInputSelect
3. SurveyInputRadio
每个问题/输入都是不同的组成部分是有道理的,因为每个问题/输入都需要自己的标记(例如<input type="text">vs <input type="radio">),并且每个都需要自己的道具,方法等。但是,这些组件将有很多共同之处:
· 一个问题
· 验证功能
· 错误状态
等等所以我认为这是扩展组件的好用例!
基本组件
每个子组件都将从一个名为的文件组件继承SurveyInputBase。注意以下几点:
· 该question道具将是在每个组件常见。我们可以添加更多的常用选项,但是对于这个简单的示例,我们坚持使用一个。
· 我们以某种方式需要将这个组件中的道具复制到任何扩展组件。
· 我们以某种方式需要为模板内的不同输入插入标记。
SurveyInputBase.vue
<template>
<pclass="survey-base">
<h4>{{ question }}</h4>
<!--the appropriate input should go here-->
</p></template><script>
exportdefault{
props:[question],
}</script>
继承组件选项
暂时忘掉模板,我们如何让每个子组件继承道具?每个人都需要question作为道具,以及他们自己独特的道具:
这可以通过导入基本组件并使用以下exts选项指向它来实现:
SurveyInputText.vue
<template>
<!--How to include the question here???-->
<input:placeholder="placeholder"></template><script>
importSurveyInputBasefrom./SurveyInputBase.vue;
exportdefault{
exts:SurveyInputBase,
props:[placeholder],
}</script>
看Vue Devtools,我们可以看到使用exts确实给了我们在我们的子组件中的基本道具:
合并策略
您可能想知道子组件如何继承该question道具而不是覆盖它。该exts选项实现合并策略,可确保您的选项正确组合。例如,如果道具名称不同,它们显然都会被包括在内,但如果它们具有相同的名称,则Vue会优先选择子组件。
合并策略也适用于其他选项,如方法,计算属性和生命周期钩子,并将它们与类似的逻辑相结合。查看文档以了解Vue如何执行它的确切逻辑,但是如果需要,您可以定义自己的自定义策略。
注意:也可以选择mixin在组件中使用属性而不是exts。exts不过,我更喜欢这个用例,因为它有一个稍微不同的合并策略,使得子组件选项具有更高的优先级。
扩展模板
扩展组件的选项相当简单 - 但模板呢?
合并策略不适用于该template选项。我们要么继承基本模板,要么我们定义一个新模板并覆盖它。但是我们怎么能把它们结合起来
我的解决方案是使用Pug预处理器。它附带include和exts选项,所以它似乎很适合这种设计模式。
基本组件
首先,让我们将基础组件的模板转换为Pug语法:
<templatelang="pug">
p.survey-base
h4
block input</template>
注意以下几点:
· 我们添加lang="pug"到我们的模板标签中,告诉vue-loader将它作为帕格模板来处理(另外,别忘了将帕格模块添加到您的项目中npm i --save-dev pug)
· 我们block input用来声明子组件内容的出口。
所以这里就是稍微凌乱的地方。如果我们希望我们的子组件扩展这个模板,我们需要把它放到它自己的文件中:
SurveyInputBase.pug
p.survey-base
h4 {{ question }}
block input
然后我们将include这个文件放在我们的基本组件中,这样它仍然可以作为一个普通的独立组件使用:
SurveyInputBase.vue
<templatelang="pug">
include SurveyInputBase.pug</template><script>
exportdefault{
props:[question]
}</script>
要做到这一点是很可耻的,因为它会挫败“单个文件”组件的目的,但对于这种用例,我认为这是值得的。可能你可以制作一个定制的webpack加载程序来避免这样做。
子组件
现在让我们将我们的子组件的模板转换为帕格:
SurveyInputText.vue
<templatelang="pug">
exts SurveyInputBase.pug
block input
input(type="text" :placeholder="placeholder")</template><script>
importSurveyInputBasefrom./SurveyInputBase.vue;
exportdefault{
exts:SurveyInputBase,
props:[placeholder],
}</script>
子组件使用extsPug 的功能,其中包含基础组件,并输出input块中的任何自定义内容(一种与插槽无关的概念)。
以下是在扩展基础并将其转换回常规HTML Vue模板之后,子组件的模板的实际外观:
<pclass="survey-base">
<h4>{{ question }}</h4>
<inputtype="text":placeholder="placeholder"></p>
把它们放在一起
使用这种策略,我们可以继续创建其他两个子组件,SurveyInputSelect并SurveyInputRadio使用它们自己的道具和标记。
如果我们在项目中使用它们,我们的主模板可能如下所示:
<survey-input-text
question="1. What is your name?"
placeholder="e.g. John Smith"></survey-input-text><survey-input-select
question="2. What is your favorite UI framework?"
:options="[React, Vue.js, Angular]"></survey-input-select><survey-input-radio
question="3. What back do you use?"
:options="[Node.js, Laravel, Ruby]"
name="back"></survey-input-radio>
这里是渲染的标记:
<pclass="survey-base">
<h4>1. What is your name?</h4>
<inputtype="text"placeholder="e.g. John Smith"></p><pclass="survey-base">
<h4>2. What is your favorite UI framework?</h4>
<select>
<option>React</option>
<option>Vue.js</option>
<option>Angular</option>
</select></p><pclass="survey-base">
<h4>3. What back do you use?</h4>
<p><inputtype="radio"name="back"value="Node.js">Node.js</p>
<p><inputtype="radio"name="back"value="Laravel">Laravel</p>
<p><inputtype="radio"name="back"value="Ruby">Ruby</p></p>
注意:我们也可以实例化SurveyInputBase组件,因为它可以独立工作,但在这个例子中并不是真的需要。不过,我认为这是一个重要的观点。
Vue应用程序中使用共享类似选项甚至模板标记组件的几种方式
下一篇:返回列表