Vue应用程序中使用共享类似选项甚至模板标记组件的几种方式

交互设计

  您的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组件,因为它可以独立工作,但在这个例子中并不是真的需要。不过,我认为这是一个重要的观点。

标签: 交互设计