【问题标题】:Do we have router.reload in vue-router?我们在 vue-router 中有 router.reload 吗?
【发布时间】:2017-05-09 03:20:13
【问题描述】:

我在这个pull request看到:

  • 添加router.reload()

    使用当前路径重新加载并再次调用数据挂钩

但是当我尝试从 Vue 组件发出以下命令时:

this.$router.reload()

我收到此错误:

Uncaught TypeError: this.$router.reload is not a function

我在docs 中进行了搜索,但找不到任何相关内容。 vue/vue-router 是否提供类似这样的功能?

我感兴趣的软件版本是:

"vue": "^2.1.0",
"vue-router": "^2.0.3",

PS。我知道location.reload() 是其中一种选择,但我正在寻找原生 Vue 选项。

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-router reload


    【解决方案1】:

    this.$router.go() 正是这样做的;如果未指定参数,则路由器导航到当前位置,刷新页面。

    注意:当前的 implementation of routerits history components 没有将参数标记为可选,但 IMVHO 它是 Evan You 的错误或遗漏,因为 the spec explicitly allows itI've filed an issue report about it. 如果你真的关心当前的 TS 注释,只需使用等效的 this.$router.go(0)

    至于“为什么会这样”:go 在内部将其参数传递给window.history.go,因此它等于windows.history.go() - 这反过来又会根据MDN doc 重新加载页面。

    注意:由于这会在常规桌面(非便携式)Firefox 上执行“软”重新加载,如果您使用它可能会出现一堆奇怪的怪癖,但实际上您需要真正的重新加载;使用 OP 提到的 window.location.reload(true); (https://developer.mozilla.org/en-US/docs/Web/API/Location/reload) 可能会有所帮助 - 它确实解决了我在 FF 上的问题。

    【讨论】:

    【解决方案2】:

    最简单的解决方案是在 : 中添加 :key 属性

    <router-view :key="$route.fullPath"></router-view>
    

    这是因为如果同一组件被处理,Vue Router 不会注意到任何变化。使用该键,对路径的任何更改都将触发使用新数据重新加载组件。

    【讨论】:

    • 官方文档中的vuejs.org/v2/api/#key间接解释了vue中key特殊属性的机制。
    • 这行不通,因为在 OP 正在讨论的场景中,完整路径不会改变。
    • 对我来说效果很好。赞成这个答案。
    • 终于知道密钥是干什么用的了。谢谢你解决了我的问题
    • router-viewkeep-alive 结合使用时,key 必须放在component 本身上,如本答案中所述stackoverflow.com/questions/66215625/…
    【解决方案3】:
    this.$router.go(this.$router.currentRoute)
    

    Vue-Router 文档:

    我在 GitHub 上查看了 vue-router repo,似乎没有 reload() 方法了。但在同一个文件中,有:currentRoute 对象。

    来源:vue-router/src/index.js
    文档:docs

    get currentRoute (): ?Route {
        return this.history && this.history.current
      }
    

    现在您可以使用this.$router.go(this.$router.currentRoute) 重新加载当前路线。

    简单的example

    此答案的版本:

    "vue": "^2.1.0",
    "vue-router": "^2.1.1"
    

    【讨论】:

    • 这不会刷新Safari上的任何数据
    • 有没有办法只重新加载组件,而不刷新页面?路线应该是相同的,比如说'/users'。但是当我点击刷新按钮时,它必须刷新整个页面,而不需要重新加载页面。
    【解决方案4】:

    如果您使用 Typescript,请使用 router.go(0),它会询问 go 方法的参数。

    【讨论】:

      【解决方案5】:

      路由器.js

      routes: [
      {
        path: '/',
        component: test,
        meta: {
          reload: true,
        },
      }]
      

      main.js

      import router from './router';
      
      new Vue({
        render: h => h(App),
        router,
        watch:{
          '$route' (to) {
             if(to.currentRoute.meta.reload==true){window.location.reload()}
        }
      }).$mount('#app')
      

      【讨论】:

        【解决方案6】:

        解析到 URL 的路由并使用 Javascript 导航窗口。

                let r = this.$router.resolve({
                name: this.$route.name, // put your route information in
                params: this.$route.params, // put your route information in
                query: this.$route.query // put your route information in
              });
              window.location.assign(r.href)

        此方法替换 URL 并导致页面执行完整请求(刷新),而不是依赖 Vue.router。 $router.go 对我来说并不一样,即使理论上应该这样做。

        【讨论】:

          【解决方案7】:

          这是我的重载。因为有些浏览器很奇怪。 location.reload 无法重新加载。

          methods:{
             reload: function(){
                this.isRouterAlive = false
                setTimeout(()=>{
                   this.isRouterAlive = true
                },0)
             }
          }
          
          <router-view v-if="isRouterAlive"/>
          

          【讨论】:

            【解决方案8】:
            `<router-link :to='`/products`' @click.native="$router.go()" class="sub-link"></router-link>`
            

            我已经尝试过重新加载当前页面。

            【讨论】:

              【解决方案9】:

              如果您只想更新页面上的某些组件,这里有一个解决方案:

              在模板中

              <Component1 :key="forceReload" />
              <Component2 :key="forceReload" />
              

              在数据中

              data() {
                return {
                  forceReload: 0
                {
              }
              

              在方法中:

                 Methods: {
                   reload() {
                      this.forceReload += 1
                   }
                 }
              

              使用唯一键并将其绑定到要更新的每个组件的数据属性(我通常只需要一个组件,最多两个。如果您需要更多,我建议使用刷新整个页面其他答案。

              我从 Michael Thiessen 的帖子中了解到这一点: https://medium.com/hackernoon/the-correct-way-to-force-vue-to-re-render-a-component-bde2caae34ad

              【讨论】:

                【解决方案10】:

                2021 年 12 月更新:

                您可以通过添加 :key="$route.fullPath" 来强制重新加载组件。

                对于组件:

                <Child :key="$route.fullPath" />
                

                对于router-view标签:

                <router-view :key="$route.fullPath" />
                

                但是,:key="$route.fullPath" 只能强制重载不同路由的组件,不能强制重载同一路由的组件。为了能够强制重新加载同一路由的组件,我们需要将"value"与数组添加到:key="$route .fullPath"更改“值”。所以它变成了:key="[$route.fullPath, value]",我们需要改变“value”

                *我们可以将 Array 分配给 :key=

                <template>
                  <Child 
                    :key="[$route.fullPath, value]" // Can assign "Array" to ":key="
                    @childReload="reload" // Call @click="$emit('childReload')" in   
                  />                      // Child Component to increment the value.
                </template> 
                
                    OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR
                
                <template>
                  <router-view 
                    :key="[$route.fullPath, value]" // Can assign "Array" to ":key="
                    @routerViewReload="reload" // Call @click="$emit('routerViewReload')"
                  />                           // in Child Component to increment the value.
                </template>
                    
                <script>
                export default {
                  name: "Parent", components: { Child, },
                  data() {
                    return {
                      value: 0,
                    };
                  },
                  methods: {
                    reload() {
                      this.value++;
                    }
                  }
                }
                </script>
                

                但是,要同时使用 "$route.fullPath" 和 "value" 有时会导致一些错误,所以只有当 Click 等事件发生时,我们才会同时使用 “$route.fullPath” 和 “value”。除了像 Click 这样的事件发生时,我们总是只需要使用 "$route.fullPath"

                这是最终代码:

                <template>
                  <Child 
                    :key="state ? $route.fullPath : [$route.fullPath, value]"
                    @childReload="reload" // Call @click="$emit('childReload')" in
                  />                      // Child Component to increment the value.
                </template>
                    
                    OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR
                    
                <template>
                  <router-view 
                    :key="state ? $route.fullPath : [$route.fullPath, value]"
                    @routerViewReload="reload" // Call @click="$emit('routerViewReload')" in
                  />                           // Child Component to increment the value.
                </template>
                        
                <script>
                export default {
                  name: "Parent", components: { Child, },
                  data() {
                    return {
                      state: true,
                      value: 0,
                    };
                  },
                  methods: {
                    reload() {
                      this.state = false;
                      this.value++;
                      this.$nextTick(() => this.state = true);
                    }
                  }
                }
                </script>
                

                不幸的是,没有简单的方法可以在 Vue 中正确地强制重新加载组件。这就是Vue需要解决的问题。

                【讨论】:

                  【解决方案11】:
                  function removeHash () { 
                      history.pushState("", document.title, window.location.pathname
                                                            + window.location.search);
                  }
                  
                  
                  App.$router.replace({name:"my-route", hash: '#update'})
                  App.$router.replace({name:"my-route", hash: ' ', params: {a: 100} })
                  setTimeout(removeHash, 0)
                  

                  注意事项:

                  1. # 后面必须有一些值。
                  2. 第二个路由哈希是一个空格,不是空字符串。
                  3. setTimeout,而不是 $nextTick 以保持网址干净。

                  【讨论】:

                    【解决方案12】:

                    对于重新渲染,您可以在父组件中使用

                    <template>
                      <div v-if="renderComponent">content</div>
                    </template>
                    <script>
                    export default {
                       data() {
                          return {
                            renderComponent: true,
                          };
                        },
                        methods: {
                          forceRerender() {
                            // Remove my-component from the DOM
                            this.renderComponent = false;
                    
                            this.$nextTick(() => {
                              // Add the component back in
                              this.renderComponent = true;
                            });
                          }
                        }
                    }
                    </script>
                    

                    【讨论】:

                      【解决方案13】:

                      简单的重新加载/刷新任何组件做下面的事情

                      <ProductGrid v-if="renderComponent"/>
                      
                      <script>
                      import ProductGrid from "./product-grid";
                      export default {
                        name:'product',
                        components: {
                          ProductGrid
                        },
                        data() {
                          return {
                            renderComponent: true,
                          };
                        },
                        methods: {
                          forceRerender: function() {
                            // Remove my-component from the DOM
                              this.renderComponent = false;
                              this.$nextTick(() => {
                                  // Add the component back in
                                  this.renderComponent = true;
                              });
                          }
                       },
                       watch:{
                          '$route.query.cid'(newId, oldId) {
                              if(newId>0){
                                  this.forceRerender();
                              }      
                           }
                        }
                      }
                      </script>
                      

                      【讨论】:

                        【解决方案14】:
                        vueObject.$forceUpdate();
                        

                        为什么不使用 forceUpdate 方法?

                        【讨论】:

                          【解决方案15】:
                          window.location.reload();
                          

                          您可以使用它来重新加载当前页面。 Jquery中也有类似的用法。

                          【讨论】:

                          • 重新加载窗口与使用 PWA 实现的目标相反。因此,虽然该解决方案在技术上解决了问题,但对于手头的问题,它并不是一个有用的解决方案。
                          猜你喜欢
                          • 2020-10-14
                          • 1970-01-01
                          • 2021-06-07
                          • 1970-01-01
                          • 1970-01-01
                          • 2018-12-18
                          • 2023-03-24
                          • 1970-01-01
                          • 2021-08-09
                          相关资源
                          最近更新 更多