SweeTooth
@SweeTooth

Как передать props в компонент во Vue 3 через роутинг?

Возникла такая проблема при построение простенького приложения на чистом Vue 3: Имеется главный компонент в котором лежит массив posts и есть компонент Home для роутинга, в котором в свою очередь лежит компонент post.

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- google fonts -->
    <link rel="preconnect" href="https://fonts.gstatic.com" />
    <link
      href="https://fonts.googleapis.com/css2?family=Ubuntu:ital,wght@0,700;1,400&display=swap"
      rel="stylesheet"
    />
    <!-- styles -->
    <link rel="stylesheet" href="style.css" />
    <title>Posts</title>
  </head>
 <body>
   <div id="app">
      <div class="container">
        <router-view></router-view>
     </div>
   </div>
    <!-- Vue -->
    <script src="https://unpkg.com/vue@3.0.5/dist/vue.global.js"></script>
    <script src="main.js"></script>

    <!-- Vue router -->
    <script src="https://unpkg.com/vue-router@4.0.3/dist/vue-router.global.js"></script> 
     <script>
      const mountedApp = app.mount('#app')
    </script>
 </body>
</html>


main.js
const app = Vue.createApp({
  data() {
    return {
      posts: [],
    }
  }
});


router.js
const home = {
  props: ['posts'],
    template:
  /*html*/
`<h1 class="title">Latest posts</h1>
  <div class="posts">
    <post :posts="posts"></post>
  </div>`
}

const routes = [
  {path: '/', component: home},
]

const router = VueRouter.createRouter({
history:VueRouter.createWebHistory(),
routes
})
app.use(router)


Как мне передать из main.js в роут Home (который находится в route.js) массив posts через prop?
  • Вопрос задан
  • 3271 просмотр
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
Сначала пара слов о том, как правильно:

Роутинг для передачи данных в этой ситуации использовать не надо. Подключаете vuex, кладёте массив в хранилище, компонент home никаких параметров не принимает, просто достаёт из хранилища нужные данные и передаёт их в компонент posts:

<posts :posts="$store.state.posts" />

Как видите, всё элементарно.

Передача же "через роутинг" обернётся говнокодерством:

  • Можно сделать маршрут именованным и передавать через params:

    <router-link :to="{ name: 'home', params: { posts } }">home</router-link>

    this.$router.push({
      name: 'home',
      params: {
        posts: this.posts,
      },
    });

    Сразу же очевиден первый недостаток такого способа: в скольких местах осуществляется переход на роут home, столько раз придётся и передавать туда явным образом массив posts, указывая его в params каждого router-link или вызова $router.push. При этом, если переход осуществляется не из корневого компонента, то, чтобы дотянуться до posts, придётся ещё и $root использовать. В случае же, когда пользователь решит осуществить переход посредством адресной строки браузера, то ничего передать не получится.

    Ещё один недостаток станет очевидным после перехода - оказывается, элементы posts превратились в строки. Роутер приводит к строкам значения свойств params (или, если свойство является массивом, к строкам будут приведены его элементы). Так что для корректной передачи ещё придётся и в json данные конвертировать, а в компоненте home этот json парсить - говнокод, как и обещал.

  • Можно прицепить данные к router-view, тогда они будут переданы как параметры в компонент текущего маршрута: <router-view :posts="post" />.

    Тут тоже не всё пройдёт гладко - так передача параметров будет осуществляться в компоненты всех маршрутов, и там, где переданные параметры не описаны, они будут сочтены атрибутами и прицеплены к корневому элементу (если он один; когда несколько - надо явным образом указывать, куда добавлять $attrs). Чтобы передавать что надо только куда надо, можно оформить параметры, передаваемые в router-view, как вычисляемое свойство, значение которого будет зависеть от текущего маршрута:

    computed: {
      routeParams() {
        return что-то, в зависимости от this.$route;
      },
    },

    <router-view v-bind="routeParams" />

Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы