.vue
文件是否有办法以单一文件组件模式负责创建自己的Vue实例?
这是Vue文件。
// MyComponent.vue
<template><div>Hello {{ name }}!</div></template>
<script>
const Vue = require('vue');
// what would usually be exports default
const componentConfig = {
name: "my-component",
props: {
name: String,
},
};
function create(el, props) {
const vm = new Vue({
el,
render(h) {
return h(componentConfig, { props });
});
vm.$mount();
return vm;
}
module.exports = { create };
</script>
,然后在某些JS文件中使用:
// index.js
const MyComponent = require('./MyComponent.vue');
const el = '.container';
const props = {
name: 'Jess',
};
MyComponent.create(el, props);
</script>
执行上述操作时,出现无法找到模板的错误。
[Vue warn]: Failed to mount component: template or render function not defined.
found in
---> <MyComponent>
<Root>
本能地,我不理解Vue编译器将如何神奇地(希望从脚本标签中)推断出我想要引用上面声明的模板。是的有没有关于为什么我不能做到这一点的解释,或者有关于如何使它工作的想法?
答案 0 :(得分:3)
您要描述的内容是通过Webpack和Vue Loader的预编译步骤完成的。 Vue编译器实际上并未解析Single File Components。 Vue编译器 可以解析的是组件的options对象中提供的模板。因此,如果您在template
对象中提供componentConfig
选项,那么您的示例将起作用。否则,您将必须使用Webpack和Vue Loader进行预编译步骤才能解析单个文件组件的模板。为此,您必须符合SFC结构defined in the spec。这是摘录..
模板
- 每个
*.vue
文件最多可以包含一个<template>
块 时间。- 内容将被提取并传递到
vue-template-compiler
和 预编译到JavaScript渲染函数中,最后注入 进入<script>
部分中导出的组件中。脚本
- 每个
*.vue
文件一次最多可以包含一个块。- 该脚本作为ES模块执行。
- 默认导出应为Vue.js component options object。 导出由
Vue.extend()
创建的扩展构造函数 支持,但首选普通对象。- 与
.js
文件(或扩展名)匹配的任何Webpack规则 由lang
属性指定)将应用于<script>
也会阻止。
要使您的特定示例生效,您可以像这样重写main.js
文件。
const MyComponent = require("./MyComponent.vue");
const el = ".container";
const data = {
name: "Jess"
};
MyComponent.create(el, data);
还有您的MyComponent.vue
文件(就像下面提到的@Ferrybig一样,这可能是js
文件)..
<script>
const Vue = require('vue');
function create(el, data) {
const componentConfig = {
el,
name: "my-component",
data,
template: `<div>Hello {{ name }}!</div>`
};
const vm = new Vue(componentConfig);
return vm;
}
module.exports = { create };
</script>
查看此CodeSandbox
或者,如果您喜欢渲染功能,您的MyComponent.vue
将看起来像这样..
<script>
const Vue = require('vue');
function create(el, data) {
const componentConfig = {
el,
name: "my-component",
data,
render(h) { return h('div', 'Hello ' + data.name) }
};
const vm = new Vue(componentConfig);
return vm;
}
module.exports = { create };
</script>
要记住的最后一件事:在任何组件中,您都可以使用模板或渲染功能,但不能像示例中那样使用,但不能同时使用这两种功能。这是因为其中一个将覆盖另一个。例如,请参见JSFiddle Vue boilerplate,并注意如何when you add a render function覆盖模板。这可以解释您遇到的错误。渲染函数具有优先权,但是您向它提供了一个组件的options对象,该对象不提供要渲染的模板。
PS:尽管如此,我对这项练习的目的还是很感兴趣。当然,这不是在Vue中处理问题的推荐方法。
答案 1 :(得分:3)
您确实已经接近可行的解决方案,但是您缺少一些将所有内容组合在一起的“胶水”部分:
<template>
<div>Hello {{ name }}!</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
import Vue from "vue";
const Component = {
// Add data here that normally goes into the "export default" section
name: "my-component",
props: {
name: String,
},
data() {
return {
};
},
};
Component.create = function(el, props) {
const vm = new Vue({
el,
render(h) {
return h(Component, { props });
},
});
vm.$mount();
return vm;
};
export default Component;
</script>
然后可以在其他文件中如下使用它:
import App from "./App";
App.create("#app", {
name: 'Hello World!',
});
关于代码框的示例:https://codesandbox.io/s/m61klzlwy