javascript - Vue.js 路由器。将方法放在应用程序中还是组件中?

标签 javascript vuejs2 vue-component

我创建了这个 Vue.js 路由器示例来让我了解路由的工作原理。我故意从 CDN 加载所有内容,以便任何人看到这个后,都可以立即开始学习,而不必学习如何导入依赖项等。

我的问题是,我应该在哪里放置根据该路由的路由参数从 JSON API 获取数据的方法?在应用程序中,还是在组件中?

如果我的问题看起来很幼稚,请原谅。我想我已经快到了。

运行代码片段,然后单击“整页”以更好地查看。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Simple Vue.js Router Example</title>

    <!-- VUE JS v2.6.1 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <!-- VUE ROUTER JS v3.1.3 -->
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <!-- BOOTSTRAP CSS v4.3.1 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <!-- GOOGLE FONT CSS - Roboto Mono -->
    <link href="https://fonts.googleapis.com/css?family=Roboto+Mono:100,300,400,500,700&display=swap" rel="stylesheet">
    <!-- GOOGLE FONT CSS - Material Icons -->
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

    <style type="text/css">

      body { 
        font-family: 'Roboto Mono', monospace;
        font-weight: 400;
        font-size: 1rem;
        background-color: #e0e0e0;
      }

      .active {
        color: #f44336;
      }
    </style>

  </head>

  <body>

    <!-- VUE APP - PARENT CONTAINER -->
    <div id="app" class="container">

      <!-- HEADER CONTAINER -->
      <header>
        <hr>
        <h1>Header</h1>
        <p>Static header text</p>
        <ul>
          <li>
            <router-link to="/">/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</router-link>
          </li>
          <li>
            <router-link to="/users">/users</router-link>
          </li>
          <li>
            <router-link to="/users/123">/users/123</router-link>
          </li>
          <li>
            <router-link to="/posts">/posts</router-link>
          </li>
          <li>
            <router-link to="/posts/456">/posts/456</router-link>
          </li>
          <li>
            <router-link to="/unsaved-changes">/unsaved-changes</router-link>
          </li>
          <li>
            <router-link to="/unknown-route/789">/unknown-route/789</router-link>
            <br>
            <small>*forwards to route /404</small>
          </li>
        </ul>

      </header>

      <!-- MAIN CONTAINER -->
      <main>
        <hr>
        <h1>Main</h1>
        <p>Static main text</p>

        <router-view name="routerView0"></router-view>
        <router-view name="routerView1"></router-view>
        <router-view name="routerView2"></router-view>
        <router-view name="routerView3"></router-view>
        <router-view name="routerView4"></router-view>
        <router-view name="routerView5"></router-view>
        <router-view name="routerView6"></router-view>

      </main>


      <!-- FOOTER CONTAINER -->
      <footer>
        <hr>
        <h1>Footer</h1>
        <p>Static footer text</p>

      </footer>

    </div>

    <!-- JAVA SCRIPT -->
    <script type="text/javascript">

      // DISABLE
      Vue.config.productionTip = false;
      // DISABLE
      Vue.config.devtools = false;

      // COMPONENT 0
      const Component0 = { 

        template: 
        `
        <div style="background-color: #bcaaa4;">
          <strong>Component 0</strong>
          <br>
          success: route /
          <br>
          result: component rendered.
        </div>
        `
      }

      // COMPONENT 1
      const Component1 = { 

        template: 
        `
        <div style="background-color: #80deea;">
          <strong>Component 1</strong>
          <br>
          success: route /users
          <br>
          result: component rendered.
        </div>
        `
      }

      // COMPONENT 2
      const Component2 = { 

        template: 
        `
        <div style="background-color: #80deea;">
          <strong>Component 2</strong>
          <br>
          success: route /users/{{ $route.params.id }}
          <br>
          result: component rendered.
        </div>
        `
      }

      // COMPONENT 3
      const Component3 = { 

        template: 
        `
        <div style="background-color: #b39ddb;">
          <strong>Component 3</strong>
          <br>        
          success: route /posts
          <br>
          result: component rendered.
        </div>
        `
      }

      // COMPONENT 4
      const Component4 = { 

        template: 
        `
        <div style="background-color: #b39ddb;">
          <strong>Component 4</strong>
          <br>
          success: route /posts/{{ $route.params.id }}
          <br>
          result: component rendered.
        </div>
        `
      }

      // COMPONENT 5
      const Component5 = { 

        template: 
        `
        <div style="background-color: #ffe082;">
          <strong>Component 5</strong>
          <br>
          success: route /unsaved-changes
          <br>
          result: component rendered.
          <br>
          <small><strong>*If you leave this route,<br> all text typed in below will be lost.</strong></small>
          <br>
          <input type="text">
        </div>
        `,

        // IN COMPOMENT ONLY...
        beforeRouteLeave (to, from, next) {
          const answer = window.confirm('Are you sure you want to leave this route? There are unsaved changes!')
          if (answer) {
            next()
          } else {
            next(false)
          }
        }
      }


      // COMPONENT 6
      const Component6 = { 

        template: 
        `
        <div style="background-color: #ef9a9a;">
          <strong>Component 6</strong>
          <br>
          error: unknown route.
          <br>
          action: forwarded to route /404.
          <br>
          result: component rendered.
        </div>
        `
      }


      // IN THIS ROUTE I WILL RENDER THESE COMPONENTS..
      const router = new VueRouter({
        mode: 'hash',
        linkExactActiveClass: "active",

        routes: [

          // ROUTE 0
          { path: '/',
            // COMPONENT(S) TO RENDER IN ORDER
            components: {
              // ONE OR MORE...
              routerView0: Component0,
            }
          }, // END ROUTE 0

          // ROUTE 1
          { path: '/users',
            // COMPONENT(S) TO RENDER
            components: {
              // ONE OR MORE...
              routerView1: Component1,
            }
          }, // END ROUTE 1

          // ROUTE 1.1
          { path: '/users/:id',
            // COMPONENT(S) TO RENDER
            components: {
              // ONE OR MORE...
              routerView2: Component2,
            },

            // REPORT WHEN THIS ROUTE IS VISITED
            beforeEnter: (to, from, next) => {
            // ...
            console.warn('ROUTE CHANGE')
            console.log('ROUTE', 'FROM:', from.path, 'TO:', to.path);
            next();
            }
          
          }, // END ROUTE 1.1

          // ROUTE 2
          {
            path: '/posts',
            components: {
              // ONE OR MORE...
              routerView3: Component3,
            }
          }, // END ROUTE 2

          // ROUTE 2.1
          {
            path: '/posts/:id',
            components: {
              // ONE OR MORE...
              routerView4: Component4,
            }, // END ROUTE 2.1

            // REPORT WHEN THIS ROUTE IS VISITED
            beforeEnter: (to, from, next) => {
            // ...
            console.warn('ROUTE CHANGE')
            console.log('ROUTE', 'FROM:', from.path, 'TO:', to.path);
            next();
            }
            
          },

          // ROUTE UNSAVED CHANGES
          {
            path: '/unsaved-changes',
            components: {
              // ONE OR MORE...
              routerView5: Component5,
            }

          }, // END ROUTE UNSAVED  CHANGES


          // REDIRECT!
          {
            path: '*', redirect: '/404',
            // TRAP ANY UNDEFINED ROUTE AND...
            // FORWARD IT TO /404 ROUTE
          },

          // ROUTE UNDEFINED - CUSTOM PAGE
          {
            path: '/404',
            components: {
              // ONE OR MORE...
              routerView6: Component6,
            }
          }, // END ROUTE UNDEFINED

        ]
      });


      // WATCH EVERY ROUTE THAT IS VISITED
      /*
      router.beforeEach((to, from, next) => {
        // ...
        console.info('Global Route Watcher')
     
        console.log('ROUTE', 'FROM:', from.path, 'TO:', to.path);

        next();

      });
      */

      const App = new Vue({
        el: '#app',
        router,
        data: {

        },

      })


    </script>

  </body>

</html>

最佳答案

我个人在组件内部进行获取,如果您希望组件在获取数据之前渲染并添加加载动画,您可以在created或beforeCreate钩子(Hook)上获取数据,或者您可以使用beforeRouteEnter或beforeRouteUpdate钩子(Hook)组件。

我背后的逻辑如下,如果您从组件中获取数据,只需向它们传递一个新的路由参数即可更容易测试,并且您可以避免在 App 组件上执行一些复杂的逻辑,因为它不必跟踪选择哪条路线并采取相应的行动。

看看solidSingle responsibility principle

关于javascript - Vue.js 路由器。将方法放在应用程序中还是组件中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57759598/

相关文章:

javascript - yAxis 数据在右侧定位时溢出到图表上

javascript - 视口(viewport)高度和 .css()

javascript - JS indexOf 对象数组和 splice() 没有删除正确的对象

javascript - 无效的 prop : type check failed for prop "items". 预期数组,得到字符串

javascript - 将文件转换为 base64 并在 Vuejs 中添加 v-model 绑定(bind)

vue.js - 如何在 .vue 组件模板中访问初始应用程序实例的属性?

javascript - 在 Javascript 中使用 Jest 模拟整个模块

vue.js - 我可以在 .vue 文件中使用渲染函数吗

javascript - VueJS : Issue with scoped slots and IE11

javascript - 如何检测破解的JS验证?