BUPT-HJM / vue-blog

A single-user blog built with vue2, koa2 and mongodb which supports Server-Side Rendering
https://imhjm.com
MIT License
598 stars 127 forks source link

一个渲染的问题 #19

Closed Hideer closed 6 years ago

Hideer commented 6 years ago

我想问下,您存到数据库的数据是html还是什么,我存入数据库的是html标签,但是当我渲染的时候直接输出的是html便签,并没有把html标签解析

Hideer commented 6 years ago

我使用v-html插入了但是没有类似编辑器的样式。。。

Hideer commented 6 years ago

image @BUPT-HJM

Hideer commented 6 years ago

然后我仿照您的写法:但是报错 image

您能帮助我么

BUPT-HJM commented 6 years ago

https://github.com/BUPT-HJM/vue-blog/blob/master/client/src/modules/front/components/List.vue#L101

我存的是初始输入框的内容,再进行marked的

Hideer commented 6 years ago

你好,我找到了原因,是因为我front也是用axios直接请求到的数据,然后再使用marked进行处理,他就报错说参数不能为空或undefined,说明页面渲染的时候axios请求的数据还么到(我这里只试试渲染的效果);然后我发现您的写的比较复杂,大致就是讲多有的请求数据防止到vuex然后进行geter并渲染,我有一个问题:这里是怎么做到,前端并没有请求数据,而是后端将页面都返给你,您在beforecreate中执行了vuex的方法,然后调用接口,接口请求的数据存到vuex的store中,页面页面直接从store中或取,这里我有个疑问,这个过程中同样是进行了axios的请求呀,但是为什么在Network就看不到接口请求?是哪个细节我没有注意到么, @BUPT-HJM

Hideer commented 6 years ago

image 这里这回调是干嘛 的

BUPT-HJM commented 6 years ago

看不到请求是因为我是在服务端请求了

后面那个问题:这个回调用于我在调用的时候我可以用.then的形式调用,也可以写成return Promise.resolve(res);

Hideer commented 6 years ago

我看了您的代码:我分析下我理解的流程:

大体上就是这个样子,我模仿着书写了,同样也请求到结果并将store中的值改变(在mutation方法中打印是改变了的),但是此时我页面中的vuex状态并不是请求之后的那个结果,还是一个空??????

我附上代码您可以帮我看看么:

// view

<template>
    <div class="catalog-box">
        <h1>撩我页面</h1>
        <P>{{ this.$store.state.useset.marked_text }}</P>
        <p>{{ marked_text }}</p>
    </div>
</template>

<script>
import { mapGetters, mapMutations, mapActions } from "vuex";

export default {
    name:'catalog-view',
    data () {
        return {

        }
    },
    computed: {
        ...mapGetters([
            'marked_text'
        ])
    },
    watch: {

    },
    methods: {
        ...mapActions([
            'get_index_article'
        ])
    },
    preFetch(store){
        store.dispatch('get_index_article').then(()=>{
            console.log(1);
                    console.log(this.$store.state.useset.marked_text);
        });
    },
    created () {

    }
}
</script>

<style scoped lang="less">

</style>

// store

import articleApi from './../../../Api/article'
export default{
    state:{
        user_name:"Ymc",
        header_menu: false,
        marked_text: [],
    },
    mutations:{ //提交修改状态
        menu_change(state) {
            state.header_menu = !(state.header_menu)
        },
        GET_INDEX_ARTICLE(state,docs) {
            state.marked_text = docs.data;
        }
    },
    actions: {//异步进行派发修改要求
        get_index_article({commit}, data) {
            return articleApi.get_article().then((res)=>{
                commit("GET_INDEX_ARTICLE",res.data);
                return new Promise((resolve, reject) => {
                    resolve(res);
                });
            })
        },
    },
    getters: {//派生状态
        marked_text: state => state.marked_text
    }
}

//api

import Axios from 'axios'
// 为了让服务端渲染正确请求数据
if(typeof window == "undefined") {
  Axios.defaults.baseURL = 'http://127.0.0.1:4020';
}

export default {
    get_article() {
        return Axios.get(`/Api/essay/find_essay`)
    }
}

//entry-server.js
import { createApp } from "./app";

const isDev = process.env.NODE_ENV !== "production";

export default context => {
    const s = isDev && Date.now();
    // 注意下面这句话要写在export函数里供服务端渲染调用,重新初始化那store、router
    const { app, router, store } = createApp();
    return new Promise((resolve, reject) => {
        router.push(context.url);
        router.onReady(() => {
            const matchedComponents = router.getMatchedComponents();
            if (!matchedComponents.length) {
                reject({ code: 404 });
            }
            Promise.all(
                matchedComponents.map(component => {
                    if (component.preFetch) {
                        // 调用组件上的preFetch(这部分只能拿到router第一级别组件,子组件的preFetch拿不到)
                        return component.preFetch(store);
                        // return component.preFetch()
                    }
                })
            )
                .then(() => {
                    isDev && console.log(`data pre-fetch: ${Date.now() - s}ms`);
                    // 暴露数据到HTMl,使得客户端渲染拿到数据,跟服务端渲染匹配
                    context.state = store.state;
                    // context.state.posts.forEach((element, index) => {
                    //   context.state.posts[index].content = '';
                    // })
                    resolve(app);
                })
                .catch(reject);
        });
    });
};
Hideer commented 6 years ago

@BUPT-HJM

Hideer commented 6 years ago

还记得最开始我请求数据返回html页面的问题么;今天我页面中进行分页查询的时候,一旦我给get加上路由参数,则返回给我的就是首页的html代码,这是怎么回事,刚开始的时候出现这个问题,是因为我没有给koa中分配对应的路由,但是现在我已经给他分配了路由额,并且当我修改为未带/:id参数的get请求是没有问题的,一旦我带上参数,就请求到koa2返回给我 的html中去了、、、 @BUPT-HJM

Hideer commented 6 years ago

只要我一带参数 image 如上:就会无限请求

image

BUPT-HJM commented 6 years ago

第一个问题:还有一个很重要的点,前端要跟服务端状态对上,需要替换状态,看这段代码 https://github.com/BUPT-HJM/vue-blog/blob/master/client/src/modules/front/entry-client.js#L6

第二个问题:你展示的截图里根本没有id呀~不应该是/Api/essay/find_essay_page/xxxxxx

(不同问题建议开不同issue哈,解决了你可以自行close掉,再开新的)

Hideer commented 6 years ago

好的下次会开新的issue

:id只是一个参数的展位符号,不是么;我们想请求接口的时候传递什么参数我们就用?在后面添加么 @BUPT-HJM

BUPT-HJM commented 6 years ago

可是你连斜杠都没有,应该是进不了那个路由的

Hideer commented 6 years ago

我好想知道我的问题在那了,get中通过路由传参有两个方式,第一个就是/:id路由展位符;这样你要在你请求的正常路由地址后在加一个,第二个事query查询方法:使用?进行相应查询条件的传递;并且这两种获取的方式不同,/:id是通过parse进行获取;?some= someone使用query或者querying进行获取。。。对么。。。

BUPT-HJM commented 6 years ago

ctx.params.id可以拿到/:id里面的 至于第二个就是ctx.query.xxx可以拿到