Vue 3的Vue-Router:取消路径导航后是否恢复选择元素中的更改?

rxztt3cl  于 12个月前  发布在  Vue.js
关注(0)|答案(2)|浏览(108)

样本代码:

<script setup lang="ts">
import {useRoute, onBeforeRouteUpdate, useRouter} from "vue-router";

const route = useRoute();
const router = useRouter()

onBeforeRouteUpdate((to, from, next) => {
  const result = confirm("Are you sure you want to leave? You will lose any unsaved changes.");
  if (result) {
    next();
  } else {
    next(false);
  }
});

async function updateRoute(event) {
  await router.push({params: {state: event.target.value}});
}

const states = ["eating", "idle", "walking"]
</script>

<template>

  <select @change="updateRoute">
    <option value="">Please select one</option>
    <option v-for="state in states" :value="state" :selected="state == route.params.state">{{state }}</option>
  </select>

</template>

我使用onBeforeRouterUpdate在导航离开所选选项之前提示用户。这与预期的一样工作,只是当取消导航时,select元素不会恢复到先前选择的选项。
例如,如果我从状态“吃”到状态“走”,我的当前路线参数将是“吃”。如果我取消导航到“步行”,路线参数将保持预期的“吃”。但是,选择元素将显示“walking”为选中状态。

我可以看到url参数仍然像预期的那样显示“eating”,但是所选的选项没有反映这一点。这也可以防止在我切换回“吃”时触发更改事件。
当导航被取消时,将选择恢复到当前路由器参数的最优雅的方法是什么?有没有一种方法可以触发一个React性事件或以其他方式重新呈现选择选项,以正确显示选定的状态?

fwzugrvs

fwzugrvs1#

问题是select的值需要重置:

<script setup lang="ts">
import {useRoute, onBeforeRouteUpdate, useRouter} from "vue-router";

const route = useRoute();
const router = useRouter();
const selectRef = ref()

onBeforeRouteUpdate((to, from, next) => {
  const result = confirm("Are you sure you want to leave? You will lose any unsaved changes.");
  if (result) {
    next();
  } else {
    next(false);
    selectRef.value.value = from.params.state;
  }
});

async function updateRoute(event) {
  await router.push({params: {state: event.target.value}});
}

const states = ["eating", "idle", "walking"]
</script>

<template>

  <select @change="updateRoute" ref="selectRef">
    <option value="">Please select one</option>
    <option v-for="state in states" :value="state" :selected="state == route.params.state">{{state }}</option>
  </select>

</template>
x6h2sr28

x6h2sr282#

这是因为<select>的值甚至在提示用户之前就已经更改了,并且在您的代码中没有取消更改或恢复更改的逻辑。你可以做的是为<select>使用一个ref(这将取代你的逻辑,它只是一个双向绑定,然后你可以利用它来编程地改变你代码中的值),并使用一个watcher来观察它的变化。这样,您就可以拦截任何更改,并在需要时恢复它们。这就是更新后的代码的样子:

<script setup lang="ts">
import { ref, watch } from "vue"
import { useRoute, useRouter } from "vue-router";

const route = useRoute();
const router = useRouter();
const selectRef = ref(null);  // we initialize with null

async function updateRoute(event) {
  await router.push({params: {state: event.target.value}});
};

// Won't be triggered until the component is mounted
watch(selectRef, (oldVal, newVal) => {
  const result = confirm("Are you sure you want to leave? You will lose any unsaved changes.");
  if (result) {
    await updateRoute();
  } else {
    // Undo the change
    selectRef.value = oldVal
  }
});

const states = ["eating", "idle", "walking"]
</script>

<template>

  <select ref="selectRef">
    <option value="">Please select one</option>
    <option v-for="state in states" :value="state" :selected="state == route.params.state">{{state }}</option>
  </select>

</template>

相关问题