Ошибка Vue js: шаблон компонента должен содержать ровно один корневой элемент
Я не знаю, что такое ошибка, до сих пор я тестирую через консольный журнал, чтобы проверить изменения после выбора файла (для загрузки).
Когда я запускаю $ npm run watch
, я получаю следующую ошибку:
"Webpack просматривает файлы...
95% излучение
ОШИБКА Не удалось скомпилировать с 1 ошибкой
19:42:29
ошибка./resources/assets/js/components/File.vue
(Испускаемое значение вместо экземпляра Error) Синтаксис шаблона Vue Ошибка:
Шаблон компонента должен содержать ровно один корневой элемент. если ты используют v-if на нескольких элементах, используйте v-else-if, чтобы связать их вместо этого.
@./resources/assets/js/components/AvatarUpload.vue 5: 2-181 @. /resources/assets/js/app.js @multi./resources/assets/js/app.js. /resources/assets/sass/app.scss"
My File.vue
<template>
<div class="form-group">
<label for="avatar" class="control-label">Avatar</label>
<input type="file" v-on:change="fileChange" id="avatar">
<div class="help-block">
Help block here updated 4 🍸 ...
</div>
</div>
<div class="col-md-6">
<input type="hidden" name="avatar_id">
<img class="avatar" title="Current avatar">
</div>
</template>
<script>
export default{
methods: {
fileChange(){
console.log('Test of file input change')
}
}
}
</script>
Любые идеи о том, как это решить? Какова на самом деле ошибка?
Ответы
Ответ 1
У вас есть два корневых элемента в вашем шаблоне.
<div class="form-group">
...
</div>
<div class="col-md-6">
...
</div>
И вам нужен один.
<div>
<div class="form-group">
...
</div>
<div class="col-md-6">
...
</div>
</div>
По сути, в Vue у вас должен быть только один корневой элемент в ваших шаблонах.
Ответ 2
Вам нужно обернуть весь html в один элемент.
<template>
<div>
<div class="form-group">
<label for="avatar" class="control-label">Avatar</label>
<input type="file" v-on:change="fileChange" id="avatar">
<div class="help-block">
Help block here updated 4 🍸 ...
</div>
</div>
<div class="col-md-6">
<input type="hidden" name="avatar_id">
<img class="avatar" title="Current avatar">
</div>
</div>
</template>
<script>
export default{
methods: {
fileChange(){
console.log('Test of file input change')
}
}
}
</script>
Ответ 3
если по каким-либо причинам вы не хотите добавлять обертку (в моем первом случае это было для компонентов <tr/>
), вы можете использовать функциональный компонент.
Вместо того, чтобы иметь один components/MyCompo.vue
вас будет несколько файлов в папке components/MyCompo
:
-
components/MyCompo/index.js
-
components/MyCompo/File.vue
-
components/MyCompo/Avatar.vue
С помощью этой структуры способ, которым вы называете свой компонент, не изменится.
components/MyCompo/index.js
файла components/MyCompo/index.js
:
import File from './File';
import Avatar from './Avatar';
const commonSort=(a,b)=>b-a;
export default {
functional: true,
name: 'MyCompo',
props: [ 'someProp', 'plopProp' ],
render(createElement, context) {
return [
createElement( File, { props: Object.assign({light: true, sort: commonSort},context.props) } ),
createElement( Avatar, { props: Object.assign({light: false, sort: commonSort},context.props) } )
];
}
};
И если у вас есть какая-то функция или данные, используемые в обоих шаблонах, они передаются как свойства и что это!
Я позволю себе представить список компонентов и так много функций с этим шаблоном.
Ответ 4
Для более полного ответа: http://www.compulsivecoders.com/tech/vuejs-component-template-should-contain-exactly-one-root-element/
Но в основном:
- В настоящее время шаблон VueJS может содержать только один корневой элемент (из-за проблемы рендеринга).
- В тех случаях, когда вам действительно нужно иметь два корневых элемента, потому что структура HTML не позволяет вам создавать родительский элемент для переноса, вы можете использовать vue-фрагмент.
Чтобы установить его:
npm install vue-fragment
Чтобы использовать это:
import Fragment from 'vue-fragment';
Vue.use(Fragment.Plugin);
// or
import { Plugin } from 'vue-fragment';
Vue.use(Plugin);
Затем в вашем компоненте:
<template>
<fragment>
<tr class="hola">
...
</tr>
<tr class="hello">
...
</tr>
</fragment>
</template>
Ответ 5
Компонент шаблона должен содержать ровно один корневой элемент. Если вы используете v-if для нескольких элементов, используйте вместо них v-else-if.
Правильный подход
<template>
<div> <!-- The root -->
<p></p>
<p></p>
</div>
</template>
Неправильный подход
<template> <!-- No root Element -->
<p></p>
<p></p>
</template>
Многокорневые компоненты
Способ решения этой проблемы заключается в использовании функциональных компонентов, которые являются компонентами, в которых вы не должны передавать никаких реактивных данных, что означает, что компонент не будет следить за какими-либо изменениями данных, а также не будет сам обновляться при изменении чего-либо в родительском компоненте.
Поскольку это обходной путь, он идет с ценой, функциональным компонентам не передаются какие-либо хуки жизненного цикла, они меньше экземпляра, и вы больше не можете ссылаться на this
, и все передается с контекстом.
Вот как вы можете создать простой функциональный компонент.
Vue.component('my-component', {
// you must set functional as true
functional: true,
// Props are optional
props: {
// ...
},
// To compensate for the lack of an instance,
// we are now provided a 2nd context argument.
render: function (createElement, context) {
// ...
}
})
Теперь, когда мы подробно рассмотрели функциональные компоненты, давайте рассмотрим, как создавать многокорневые компоненты, для этого я приведу общий пример.
<template>
<ul>
<NavBarRoutes :routes="persistentNavRoutes"/>
<NavBarRoutes v-if="loggedIn" :routes="loggedInNavRoutes" />
<NavBarRoutes v-else :routes="loggedOutNavRoutes" />
</ul>
</template>
Теперь, если мы посмотрим на шаблон NavBarRoutes
<template>
<li
v-for="route in routes"
:key="route.name"
>
<router-link :to="route">
{{ route.title }}
</router-link>
</li>
</template>
Мы не можем сделать что-то подобное, мы будем нарушать ограничение одного корневого компонента
Решение Сделайте этот компонент функциональным и используйте рендер
{
functional: true,
render(h, { props }) {
return props.routes.map(route =>
<li key={route.name}>
<router-link to={route}>
{route.title}
</router-link>
</li>
)
}
Здесь у вас есть это вы создали многокорневой компонент, счастливое кодирование
Ссылка для более подробной информации посетите: https://blog.carbonteq.com/vuejs-create-multi-root-components/
Ответ 6
Я был сбит с толку, так как знал, что VueJS должен содержать только 1 корневой элемент, и все же я все еще получаю ту же самую "ошибку синтаксиса шаблона. Шаблон компонента должен содержать ровно один корневой элемент..." на чрезвычайно простом компоненте. Оказывается, я только что неправильно ввел </template> как </tempate>, и это дало мне ту же ошибку в нескольких файлах, которые я скопировал и вставил. Таким образом, проверьте ваш синтаксис на наличие ошибок в вашем компоненте.