Ошибка 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>

Любые идеи о том, как это решить? Какова на самом деле ошибка?

Ответ 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>, и это дало мне ту же ошибку в нескольких файлах, которые я скопировал и вставил. Таким образом, проверьте ваш синтаксис на наличие ошибок в вашем компоненте.