【问题标题】:Props not updated when set from router从路由器设置时道具未更新
【发布时间】:2019-11-25 13:00:31
【问题描述】:

当我在路由定义中设置组件道具时,观察者不起作用并且视图永远不会更新。

在此示例中,更新正常工作:

const Home = { template: '<div>Home</div>' }
const Test = {
template: '<div>Test : {{ nb }}<br><button @click="addOne" type="button">+1</button></div>',
props: {nb: Number},
methods: {
  addOne() {
    this.nb++
  }
}
}

const router = new VueRouter({
  routes: [
    { path: '/', component: Home },
    { name: 'test', path: '/test/:nb', component: Test, props: true }
  ]
})

new Vue({
	router,
  el: '#app'
})
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
<script src="https://npmcdn.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <router-link to="/">/home</router-link>
  <router-link :to="{ name: 'test', params: { nb: 42 }}">/test</router-link>
  <router-view></router-view>
</div>

注意:此示例显示“直接更改道具”警告,但这只是为了简单起见,它与问题无关,因为我没有在我的代码中这样做。

在这个例子中更新不起作用:

const Home = { template: '<div>Home</div>' }
const Test = {
template: '<div>Test : {{ counter.value }}<br><button @click="addOne" type="button">+1</button></div>',
props: {counter: Object},
methods: {
  addOne() {
    this.counter.value++
    console.log('new value : ' + this.counter.value)
  }
}
}

class Counter {
  constructor(value) {
    this.value = value
  }
}

const router = new VueRouter({
  routes: [
    { path: '/', component: Home },
    {
      name: 'test',
      path: '/test/:nb',
      props: (route) => ({counter: new Counter(route.params.nb)}),
      component: Test
    }
  ]
})

new Vue({
	router,
  el: '#app'
})
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
<script src="https://npmcdn.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <router-link to="/">/home</router-link>
  <router-link :to="{ name: 'test', params: { nb: 42 }}">/test</router-link>
  <router-view></router-view>
</div>

【问题讨论】:

    标签: javascript vue.js vue-router watch


    【解决方案1】:

    counter 对象不会反应,因此不会检测到属性更改。将对象作为道具传递不会增加反应性。

    我刚刚在您的示例中更改了一行:

    props: (route) => ({counter: Vue.observable(new Counter(route.params.nb))}),
    

    将对象传递给Vue.observable 将应用反应性。

    请注意,“应用反应性”意味着重写所有属性以使用 getter 和 setter。在此处介绍的简单示例中,这仅表示 value 属性,应该没问题。 Vue 只能重写它可以看到的属性,因此任何隐藏在闭包中的数据都无法访问。

    const Home = { template: '<div>Home</div>' }
    const Test = {
    template: '<div>Test : {{ counter.value }}<br><button @click="addOne" type="button">+1</button></div>',
    props: {counter: Object},
    methods: {
      addOne() {
        this.counter.value++
        console.log('new value : ' + this.counter.value)
      }
    }
    }
    
    class Counter {
      constructor(value) {
        this.value = value
      }
    }
    
    const router = new VueRouter({
      routes: [
        { path: '/', component: Home },
        {
          name: 'test',
          path: '/test/:nb',
          props: (route) => ({counter: Vue.observable(new Counter(route.params.nb))}),
          component: Test
        }
      ]
    })
    
    new Vue({
    	router,
      el: '#app'
    })
    <script src="https://npmcdn.com/vue/dist/vue.js"></script>
    <script src="https://npmcdn.com/vue-router/dist/vue-router.js"></script>
    
    <div id="app">
      <router-link to="/">/home</router-link>
      <router-link :to="{ name: 'test', params: { nb: 42 }}">/test</router-link>
      <router-view></router-view>
    </div>

    Vue 不会自动对作为 props 传递的对象应用响应性的部分原因是接收组件无论如何都不应该修改对象。这违反了单向数据流。在此示例中,您可能应该直接更新路由,而不是修改 counter 对象。

    【讨论】:

    • 感谢您的解释。我找不到有关此行为的任何文档。对于单向数据流,就像我在帖子中所说的那样,我在示例中这样做是为了保持简单。但在我的情况下,对象是通过 IPC 在后台更新的。
    猜你喜欢
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    相关资源
    最近更新 更多