9阅网

您现在的位置是:首页 > 知识 > 正文

知识

javascript - VueJS sever-side-rendering: 计算的属性在商店里看不到变化。

admin2022-11-07知识17

我试图让VueJS中的服务器端渲染工作。

我一直在遵循官方文档,我试图用axios让这个例子工作。端点是正确的,数据确实显示在了 mutation.

https:/ssr.vuejs.orgguidedata.html。

我也找到了这个页面,并尝试了大部分的例子,其中包括使用getters,vuex mapState,mapGetter等。

vue.js 2如何观察vuex的存储值

这里是 store/index.js:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

import { fetchPage } from './api'

export function createStore () {
    return new Vuex.Store({
        strict: true,

        state: () => ({
            res: {}
        }),

        actions: {
            actXY ({ commit }, page) {
                fetchPage('homepage').then((item) => {
                    commit('mutXY', { page, item });
                }).catch(error => {
                    throw new Error(`Store ${error}`);

                })
            }
        },

        mutations: {
            mutXY (state, { page, item }) {
                Vue.set(state.res, page, item);
                console.log(state.res.homepage.data)

            }
        },

        getters: {
            getXY (state) {
                return state.res
            }
        }
    })
}

控制台日志显示了正确的信息,所以这意味着axios端点正在工作并更新状态对象。原本,我是试图调用 mutation但我后来试着打电话给 getter. 遗憾的是,新的数据没有被更新到。getter所以,当然,组件中不会出现任何新的内容。

这就是 HomePage.vue:

<template>
  <div v-if="htmlData">{{ JSON.stringify(htmlData) }}</div>
  <div v-else>loading?</div>
</template>

<script>
export default ({
    name: 'homepage',

    computed: {
        htmlData () {
            console.log("computed = " + JSON.stringify(this.$store.state.res));
            console.log(this.$store.getters.getXY);
            return this.$store.getters
            // return this.getQuery()
        }
    },

    serverPrefetch () {
        return this.getData()
    },

    mounted () {
        console.log("in mounted")
        if (!this.item) {
            this.getData()
        }
    },

    methods: {
        getData () {
            return this.$store.dispatch('actXY', 'homepage')
        }
    }
})

</script>

按书面规定。htmlData 会显示。

{"getXY":{}}

是的,我确实尝试了很多其他的变化 关于如何退回商店里的物品,我想说: getter, 但是什么都没有用。

除了上面链接中的东西,我还找了一下配置文件的变化,我尝试在配置文件中添加了 async 到storeactions、getData()等。

我还尝试在组件中直接进行axios调用,一直没有成功。

由于这是一个已经在VueJS中或多或少完成的项目,我正在将其转换为SSR,我删除了package.json中的所有内容,并重新安装了每一个包,希望可能是旧的vue包中的某个包导致了冲突。

我还尝试了官方文档中的商店代码拆分,并尝试了路由的写法变化。根本没有任何效果。

我想我应该添加打印语句在我运行当前代码时的显示。

computed = undefined
computed mm  = undefined
getter = {}
computed get  = {"getXY":{}}
{
  title: 'Home'...}

组件中的计算属性运行 之前 的突变被设置。这将导致在更新突变之前调用getter。同样地,如果我试图调用改变到 res 直接从组件中调用,当商店被调用和渲染时,突变中没有任何东西。

这是我尝试运行的代码的repo。https:/github.comdt1vue-ssr-尝试。

(我想出了答案。我已经更新了我的回帖,并在下面解释了我的解决方案。)



【回答】:

第一个 storeData() => storeData(state)

那么 return this.$store.state.items.homepage.data => return this.$store.state.items.homepage && return this.$store.state.items.homepage.data (或用空主页初始化状态项)

【回答】:

Vue.js中没有SSR。开箱即用. 在你的例子中,你可以得到客户端的数据。

试试这个Store的例子。

export default new Vuex.Store({
  strict: true,
  state: {
    res: null
  },
  getters: {
    getXY(state) {
      return state.res;
    }
  },
  mutations: {
    mutXY(state, payload) {
      state.res = payload;
    }
  },
  actions: {
    actXY: function(store) {
      fetchPage("homepage")
        .then(res => {
          store.commit("mutXY", res);
        })
        .catch(error => {
          throw new Error(`Store ${error}`);
        });
    }
  }
});

你可以在组件中获取数据,就像这样

  computed: {
    htmlData() {
      return this.$store.getters.getXY;
    }
  },
  created() {
    this.getData();
  },
  methods: {
    getData() {
      return this.$store.dispatch("actXY", "homepage");
    }
  }
【回答】:

我的问题是,为什么 this.getData() 在挂载时调用?

如果我的理解是正确的,当你调用服务器端渲染时,你试图在vue组件被挂载之前渲染HTML。如果你调用 this.getData() 在创建而不是挂载?

我还会尝试其他的事情。

  1. 在组件中硬编码htmlData的值,以检查是否会呈现出来
  2. 如果可以的话,在存储中硬编码htmlData值,并检查组件是否可以获取存储数据并正确渲染。
  3. 之后也可以,通过组件的 dispatch 从服务器获取 htmlData,看看是否有效。
  4. 如果(3)行不通,可以尝试将htmlData推送到一个子组件,这个子组件是在你已经准备好htmlData的情况下才创建的,通过道具发送htmlData到子组件。
【回答】:

好吧,我终于想明白了。

我遇到的主要问题是订单外的调用。当我解决了订购问题后,我遇到了 Converting circular structure to JSON 错误。接下来是想了解VueJS、Vuex商店和axios之间的回调是如何运作的。

最后我想出的解决方案是。

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import * as util from 'util'

Vue.use(Vuex)

import { fetchPage } from './api'

export function createStore () {
    return new Vuex.Store({
        strict: true,

        state: () => ({
            res: {}
        }),

        actions: {
            actXY ({ commit }, page) {
                return fetchPage(page).then(item => {
                    commit('mutXY', { page , item } );
                })
            }
        },

        mutations: {
            mutXY (state, {page, item }) {
                Vue.set(state.res, page, item);
            }
        }
    })
}

在调用axios的时候,我必须确保只返回到 response.data 而不是整个响应。在此之前,我得到的是 unhandled promise 错误。

api.js

import Vue from 'vue';
import axios from 'axios';
import VueAxios from 'vue-axios'

Vue.use(VueAxios, axios);

Vue.axios.defaults.baseURL = '<url goes here>';

export function fetchPage(page){
    return Vue.axios.get(page).then((resp => resp.data))
}

最后但并非最不重要的是,这是 Homepage.vue.

为了启动更新,我不得不让getData()成为异步的。

<template>
<div v-if="htmlData">
  <div>{{ htmlData.title }}</div>
  <div>{{ htmlData.description }}</div>
  <div>{{ htmlData.html }}</div>
</div>
</template>

<script>
export default ({
    name: 'homepage',
    computed: {
        htmlData () {
            return this.$store.state.res.homepage
        }
    },

    serverPrefetch () {
        return this.getData()
    },
    mounted () {
        if (!this.item) {
            this.getData()
        }
    },
    methods: {
        async getData () {
            await this.$store.dispatch('actXY', 'homepage')
        }
    }
})
</script>

希望这能帮助那些遇到这些问题的人.