javascript - 是否可以从单个文件 comp 向全局 Vue 组件添加内容?
问题描述
我已经制作了一个全局组件,它将呈现我们想要的内容。
这个组件非常简单
<template>
<section
id="help"
class="collapse"
>
<div class="container-fluid">
<slot />
</div>
</section>
</template>
<script>
export default {
name: 'VHelp',
};
</script>
我在我的基本模板中使用它
<v-help />
我正在尝试从另一个使用的单个文件组件向此组件槽添加内容。
<v-help>
<p>esgssthsrthsrt</p>
</v-help>
但这在逻辑上创建了我的 comp 的另一个实例,其中包含 p 标记。这不是我想做的正确事情。
所以我尝试使用虚拟 DOM 和渲染功能,在我的comp中slot
替换。<v-elements-generator :elements="$store.state.help.helpElements" />
VHelp
storehelpElements
是一个简单的数组,里面有对象。
{
type: 'a',
config: {
class: 'btn btn-default',
},
nestedElements: [
{
type: 'span',
value: 'example',
},
{
type: 'i',
},
],
},
然后在我的VElementsGenerator
comp里面我有一个渲染函数,它在虚拟DOM中的渲染元素来自一个对象
<script>
import {
cloneDeep,
isEmpty,
} from 'lodash';
export default {
name: 'VElementsGenerator',
props: {
elements: {
type: Array,
required: true,
},
},
methods: {
iterateThroughObject(object, createElement, isNestedElement = false) {
const generatedElement = [];
for (const entry of object) {
const nestedElements = [];
let elementConfig = {};
if (typeof entry.config !== 'undefined') {
elementConfig = cloneDeep(entry.config);
}
if (entry.nestedElements) {
nestedElements.push(this.iterateThroughObject(entry.nestedElements, createElement, true));
}
generatedElement.push(createElement(
entry.type,
isEmpty(elementConfig) ? entry.value : elementConfig,
nestedElements
));
if (typeof entry.parentValue !== 'undefined') {
generatedElement.push(entry.parentValue);
}
}
if (isNestedElement) {
return generatedElement.length === 1 ? generatedElement[0] : generatedElement;
}
return createElement('div', generatedElement);
},
},
render(createElement) {
if (this.elements) {
return this.iterateThroughObject(this.elements, createElement);
}
return false;
},
};
</script>
第二种方法效果很好,但是如果我想渲染复杂的数据,渲染函数中使用的对象非常长并且读取起来很复杂。
因此,我试图找到另一种方法来将内容添加到基础布局中使用的全局组件,仅当我希望在子组件上使用它时。
我不能VHelp
直接在子组件中使用这个组件,因为 HTML 页面架构是完全错误的。
我想知道是否可以从单个文件 comp 将内容(最好是 HTML)添加到组件槽,而无需重新创建组件的新实例?
此外,我认为将 HTML 保存为 Vuex 商店中的字符串非常难看。所以我什至不知道这是否可能,以及我是否需要完全改变我尝试这样做的方式。
有任何想法吗 ?
解决方案
在商店中,您应该只存储数据而不是 HTML 结构。解决这个问题的方法是将 v-help 组件内容的当前状态存储在 store 中。然后,您将拥有一个v-help
带有插槽的组件(就像您已经提出的那样)。您应该根据商店中的状态传递不同的内容。这是一个抽象的例子:
<v-help>
<content-one v-if="$store.state.content === 'CONTENT_ONE' />
<content-two v-else-if="$store.state.content === 'CONTENT_TWO' />
<content-fallback v-else />
</v-help>
其他地方的子元素:
<div>
<button @click="$store.commit('setContentToOne')">Content 1</button>
</div>
Vuex商店:
state: {
content: null
},
mutations: {
setContentToOne(state) {
state.content = 'CONTENT_ONE';
}
}
当然,这取决于您的要求,尤其是如果这是实现此目标的最佳方式,则取决于使用了多少不同的场景。如果我理解正确,您正在将帮助元素保存到商店。您还可以在其中保存一组当前选择的帮助元素,然后直接在v-help
组件中显示它们。
编辑:
当然,您也可以只将静态组件(或其名称)保存在商店中。然后,您可以在子组件中动态决定哪些内容显示在v-help
. 这是一个例子:
<v-help>
<component :is="$store.state.helpComponent" v-if="$store.state.helpComponent !== null" />
</v-help>
测试组件:
<template>
test component
</template>
<script>
export default {
name: 'test-component'
};
</script>
其他地方的子元素(变体 1,将名称存储在 Vuex 中):
<div>
<button @click="$store.commit('setHelpComponent', 'test-component')">Set v-help component to 'test-component'</button>
</div>
其他地方的子元素(变体 2,将整个组件存储在 Vuex 中):
<template>
<button @click="$store.commit('setHelpComponent', testComponent)">Set v-help component to testComponent (imported)</button>
</template>
<script>
import TestComponent from '@/components/TestComponent';
export default {
name: 'some-child-component',
computed: {
testComponent() {
return TestComponent;
}
}
};
</script>
其他地方的子元素(变体 3,存储名称,从导入的组件派生,在 Vuex 中;我会使用这个变体):
<template>
<button @click="$store.commit('setHelpComponent', testComponentName)">Set v-help component to 'test-component'</button>
</template>
<script>
import TestComponent from '@/components/TestComponent';
export default {
name: 'some-child-component',
computed: {
testComponentName() {
return TestComponent.name;
}
}
};
</script>
Vuex商店:
state: {
helpComponent: null
},
mutations: {
setHelpComponent(state, value) {
state.helpComponent = value;
}
}
另请参阅动态组件的文档(<component :is="">
语法):https ://vuejs.org/v2/guide/components.html#Dynamic-Components
推荐阅读
- c# - 如何在 C# 中的 texbox textChanged 事件中查找特定数量的数字?
- amazon-web-services - 如何使用 AWS 用户池访问令牌访问 AWS 资源?
- javascript - 动态获取数组的整数
- ios - 不区分大小写的拆分swift 4?
- javascript - JavaScript 将两个日期时间减去秒
- github - 特定分支的 Github 拉取请求模板
- java - 获取“驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置”虽然设置正确的路径
- python - 使用 isdigit() 字符串方法时出现错误
- node.js - TensorflowJS 文本/字符串分类
- lagom - Lagom http 状态码/标头返回为 json