【问题标题】:VueJS render property inside html string using v-htmlVueJS使用v-html在html字符串中渲染属性
【发布时间】:2020-05-04 01:01:22
【问题描述】:

我有一个从编辑器获取并存储在数据库中的 html 字符串。

<h3><a href="#" rel="noopener noreferrer nofollow"><em><strong>Profile Of User:</strong></em></a></h3><p></p><p>{{user}}</p>

我想从数据库中检索它并将其呈现为 HTML。当我使用 v-html 时,它会呈现为:

<v-card-text v-html="content"></v-card-text>

用户简介:

{{用户}}

如果我有这样的数据属性,如何从数据属性渲染 {{hello}}:

data() {
        return {
            user: "Lim Socheat",
            content:"<h3><a href="#" rel="noopener noreferrer nofollow"><em><strong>Profile Of User:</strong></em></a></h3><p></p><p>{{user}}</p>"
        };
    },

预期结果:

用户简介:

林索切

因为 {{ user }} 将被呈现为 Lim Socheat

【问题讨论】:

    标签: vue.js nuxt.js


    【解决方案1】:

    使内容成为计算属性。然后像这样使用它:

      computed: {
        content() {
           return '<h3><a href="#" rel="noopener noreferrer nofollow"><em><strong>Profile Of User:</strong></em></a></h3><p></p><p>' + this.user + '</p>';
        }
      }
    

    您可以通过这种方式使用数据中定义的所有变量。

    更新: 由于 OP 从后端获取 HTML 字符串,因此他们需要在这种情况下替换变量。 我们保留了所有可能出现的变量的映射,然后我们正在动态创建一个正则表达式来替换代码中的所述键。

      computed: {
        content() {
          // keep a map of all your variables
          let valueMap = {
            user: this.user,
            otherKey: 250
          };
          let value = '<h3><a href="#" rel="noopener noreferrer nofollow"><em><strong>Profile Of User:</strong></em></a></h3><p></p><p>{{user}}</p>';
          let allKeys = Object.keys(valueMap);
          allKeys.forEach((key) => {
            var myRegExp = new RegExp('{{' + key + '}}','i');
            value = value.replace(myRegExp, valueMap[key]);
          });
          return value;
        }
      }
    

    【讨论】:

    • 嗨,在这种情况下,我不能这样做。因为我从数据库中获取 HTML STRING,所以我可以从编辑器中动态更改。我已经编辑了问题。
    • @LimSocheat 我已经更新了代码。请立即检查。
    • 您好,感谢您的回答,您的回答给了我灵感并解决了我的问题。
    【解决方案2】:

    我找到了答案。希望它在未来对某人有所帮助。

    原帖:https://forum.vuejs.org/t/evaluate-string-as-vuejs-on-vuejs2-x/20392/2

    VueJS - Interpolate a string within a string

     <template>
            <v-container>
                <v-card>
                    <v-card-title>Print</v-card-title>
                    <v-divider></v-divider>
                    <v-card-text v-html="parse(content)"></v-card-text>
                </v-card>
            </v-container>
        </template>
    
        <script>
        export default {
            data() {
                return {
                    hello: "HELLO DATA",
                    user: "Lim Socheat",
                    content: ""
                };
            },
    
            methods: {
                getLayout() {
                    this.$axios
                        .$get("/api/layout/reciept", {
                            params: {
                                type: "reciept"
                            }
                        })
                        .then(response => {
                            this.content = response.content;
                        })
                        .catch(error => {
                            this.$toast.error(error);
                        });
                },
    
                evalInContext(string) {
                    try {
                        return eval("this." + string);
                    } catch (error) {
                        try {
                            return eval(string);
                        } catch (errorWithoutThis) {
                            console.warn(
                                "Error en script: " + string,
                                errorWithoutThis
                            );
                            return null;
                        }
                    }
                },
                parse(string) {
                    return string.replace(/{{.*?}}/g, match => {
                        var expression = match.slice(2, -2);
    
                        return this.evalInContext(expression);
                    });
                }
            },
    
            computed: {
                id() {
                    return this.$route.params.id;
                }
            },
    
            watch: {
                id: {
                    handler() {
                        this.getLayout();
                    },
                    immediate: true
                }
            }
        };
        </script>
    

    【讨论】: