Недопустимый источник просмотра: «$route» vuejs

#vue.js #vue-router #vue-composition-api

#vue.js #vue-маршрутизатор #vue-composition-api

Вопрос:

У меня есть компонент Vue, который раньше работал с наблюдателем $route .
Поскольку я сделал некоторые обновления, он больше не работает, и я получаю сообщение :

[Предупреждение Vue]: Недопустимый источник просмотра: «$ route». Источником просмотра может быть только функция получения / эффекта, ссылка, реактивный объект или массив этих типов.

Вот мой package.json :

 {
    "name": "prix-de-gros.vue",
    "version": "0.1.0",
    "private": true,
    "scripts": {
        "serve": "vue-cli-service serve",
        "build": "vue-cli-service build",
        "lint": "vue-cli-service lint"
    },
    "dependencies": {
        "@vue/composition-api": "0.6.6",
        "axios": "^0.19.2",
        "chart.js": "^2.9.3",
        "core-js": "^3.6.5",
        "moment": "^2.27.0",
        "regenerator-runtime": "^0.13.7",
        "remove": "^0.1.5",
        "slugify": "^1.4.5",
        "tiptap-vuetify": "^2.24.0",
        "vue": "^2.6.12",
        "vue-i18n": "^8.21.0",
        "vue-router": "^3.4.3",
        "vuetify": "^2.3.9",
        "vuex": "^3.5.1",
        "webpack": "^4.44.1"
    },
    "devDependencies": {
        "@mdi/js": "^5.5.55",
        "@vue/cli-plugin-babel": "^4.5.4",
        "@vue/cli-plugin-eslint": "^4.5.4",
        "@vue/cli-plugin-router": "^4.5.4",
        "@vue/cli-plugin-vuex": "^4.5.4",
        "@vue/cli-service": "^4.5.4",
        "@vue/eslint-config-prettier": "^6.0.0",
        "babel-eslint": "^10.1.0",
        "eslint": "^7.7.0",
        "eslint-plugin-prettier": "^3.1.4",
        "eslint-plugin-vue": "^6.2.2",
        "moment-locales-webpack-plugin": "^1.2.0",
        "prettier": "^2.1.0",
        "sass": "^1.26.10",
        "sass-loader": "^9.0.3",
        "vue-cli-plugin-vuetify": "^2.0.7",
        "vue-template-compiler": "^2.6.12",
        "vuetify-loader": "^1.6.0"
    },
    "resolutions": {
        "prosemirror-model": "^1.11.0",
        "prosemirror-tables": "^0.9.0"
    }
}
  

и мой компонент Vue (Vue 2 с @vue/composition-api ):

 <template>
  <div class="container">
    <v-card>
      <v-toolbar dark color="primary" dense class="mb-2">
        <v-btn text @click="goToRoute({ name: 'account' })">{{ $tc("Account", 2) }}</v-btn>
        {{formatInt( data.id) }} - {{ data.label }}
        <v-spacer></v-spacer>
        <v-btn
          v-if="data.editable"
          :aria-label="$tc('Update')"
          icon
          @click="
            goToRoute({
              name: 'account-update',
              params: { id: data.id }
            })
          "
        >
          <v-icon aria-hidden="true">{{ mdiPencil }}</v-icon>
        </v-btn>
      </v-toolbar>

      <v-card-text>
        <v-row dense>
          <v-col cols="12" sm="3" class="label-col">{{ $tc("Account") }}</v-col>
          <v-col>{{ formatInt(data.id) }}</v-col>
        </v-row>
        <v-row dense>
          <v-col cols="12" sm="3" class="label-col">{{ $tc("Label") }}</v-col>
          <v-col>{{ data.label }}</v-col>
        </v-row>
        <v-row dense class="my-4">
          <v-col cols="12" sm="3" class="label-col">{{ $tc("Status") }}</v-col>
          <v-col>{{ data.status ? $tc("On") : $tc("Off") }}</v-col>
        </v-row>
        <v-row v-if="data.info" dense>
          <v-col cols="12" sm="3" class="label-col">{{ $tc("Info") }}</v-col>
          <v-col v-html="nl2br(data.info)"></v-col>
        </v-row>
      </v-card-text>
    </v-card>
  </div>
</template>

<script>
import axios from "axios";
import { mdiPencil } from "@mdi/js";
import { formatInt, nl2br } from "@/plugins/ob-helper";
import { ref,  watch } from "@vue/composition-api";

export default {
  name: "AccountView",

  setup(props, { root: { $i18n, $router, $i18nRoute, $route } }) {
    const data = ref({});

    function dataGet() {
      axios
        .get("/backend/accounts/"   $route.params.id)
        .then(r => {
          if (r.data) {
            data.value = r.data.data;
            document.title = $i18n.tc("Account", 2)   " : "   data.value.id;
          }
        })
        .catch(error => {
          if (error.response.status !== 400 amp;amp; error.response.status !== 401) {
            alert(error.response.statusText);
          }
        });
    }

    function goToRoute(o) {
      $router.push($i18nRoute(o));
    }

  watch("$route", () => dataGet());

    return {
      data,
      formatInt,
      goToRoute,
      mdiPencil,
      nl2br
    };
  }
};
</script>
  

Комментарии:

1. watch Функция не принимает строку в качестве первого аргумента. Измените watch("$route", ...) с помощью функции, которая возвращает объект маршрута, подобный watch(() => $route, ...) .

2. Я попробовал watch(() => $route, …), я не получаю сообщение об ошибке, но ничего не происходит, например, если watch не обнаруживает изменение параметров.

3. Это будет просто наблюдать за $route объектом, а не за каким-либо из дочерних элементов. Вы можете перейти { deep: true } к таким параметрам, как watch(() => $route, ..., { deep: true }) или просто наблюдать только за объектом parameters, watch(() => $route.params, ...)

4. Я пробовал их, и раньше это работало, но больше не работает, похоже, что watch не обнаруживает изменения $ route

Ответ №1:

Реактивность $route теряется, когда объект реактивного контекста разрушается (как описано в @vue/composition-api выпуске # 264). watch Метод должен сохранять ссылку на реактивный объект для поддержания его реактивности:

 export default {
  // DON'T DO THIS
  // setup(props, { root: { $route } }) {     // reactivity lost!

  // DON'T DO THIS
  // setup(props, context) {
  //   const { root: { $route } } = context   // reactivity lost!    
  // }

  setup(props, context) {
    // reactive!
    watch(() => context.root.$route, () => dataGet())
  }
}
  

ДЕМОНСТРАЦИЯ

Проверено с @vue/composition-api 1.0.0-beta.11 и Vue 2.6.11

Ответ №2:

Вам нужно указать объект наблюдения, а затем назвать объект наблюдения ключом к этому объекту. Итак:

 watch: {
  $route(to, from) {
  // react to route changes...
  }
}
  

Смотрите здесь:https://router.vuejs.org/guide/essentials/dynamic-matching.html#reacting-to-params-changes

Комментарии:

1. спасибо за ваш ответ, но я использую composition-api, и функция просмотра немного отличается. composition-api.vuejs.org/api.html#watch

2. Ах, я понимаю, извините. Я никогда не использовал composition-api. Возможно, это поможет (если вы его еще не видели): medium.com/better-programming /…