【问题标题】:VueJS2 v-html with filter带有过滤器的 VueJS2 v-html
【发布时间】:2017-06-01 00:43:13
【问题描述】:

如何使用过滤器显示原始 html?

我有这样的事情:

K.json = function( json ) {
    if( typeof json!='string' ) json = JSON.stringify( json, null, 2 );
    json = json.replace( /</g, '&lt;' ).replace( />/g, '&gt;' ); // replace(/&/g, '&amp;')
    var pattern = /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g;
    var html = json.replace( pattern, function( match ) {
        var cls = 'number';
        var suffix = '';
        if( /^"/.test( match ) ) {
            if( /:$/.test( match ) ) {
                cls = 'key';
                match = match.slice( 0, -1 );
                suffix = ':'
            } else {
                cls = 'string';
            }
        } else if( /true|false/.test( match ) ) {
            cls = 'boolean';
        } else if( /null/.test( match ) ) {
            cls = 'null';
        }
        return '<span class="' + cls + '">' + match + '</span>' + suffix;
    } );
    return html;
};
Vue.filter( 'json', K.json );

并像这样使用它们:

<div v-html="thecolumn | json"></div>

显示警告并显示不正确:

vue.js:523 [Vue warn]: Property or method "json" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. 

(在根实例中找到)

我也尝试了来自论坛的解决方案:https://laracasts.com/discuss/channels/vue/use-a-filter-custom-filter-in-v-html-property?page=1

<p v-html="this.$options.filters.json(description)"></p>

显示错误:

[Vue warn]: Error when rendering root instance: 
vue.js:3063 Uncaught TypeError: Cannot read property 'filters' of undefined
    at eval (eval at makeFunction (vue.js:8260), <anonymous>:2:2975)
    at Proxy.renderList (vue.js:3158)
    at Proxy.eval (eval at makeFunction (vue.js:8260), <anonymous>:2:2169)
    at Vue$3.Vue._render (vue.js:3054)
    at Vue$3.<anonymous> (vue.js:2430)
    at Watcher.get (vue.js:1661)
    at new Watcher (vue.js:1653)
    at Vue$3.Vue._mount (vue.js:2429)
    at Vue$3.$mount (vue.js:6000)
    at Vue$3.$mount (vue.js:8327)

在 VueJS2 上执行此操作的正确方法是什么?

【问题讨论】:

  • 我认为没有 - 在v-html 中,所有数据绑定等都被忽略了。

标签: vuejs2


【解决方案1】:

为了完整起见,您有一些选择,例如:

  • v-html="$options.filters.FILTERNAME(args)"
  • :inner-html.prop="args | FILTERNAME"
  • v-html="METHODNAME(args)",如果你创建了一个方法。

请看下面的演示。

function json(text) {
  // do your magic
  return text.toUpperCase(); // just for demo
}

Vue.filter('json', function (value) {
    return json(value);
})

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    jsonMethod(v) {
      return json(v); // create a "proxy" to the outer function
    }
  }
})
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <p v-html="$options.filters.json(message)"></p>
  
  <p :inner-html.prop="message | json"></p>
  
  <p v-html="jsonMethod(message)"></p>
</div>

【讨论】:

  • 很惊讶官方文档中没有记录这些选项。
  • 我以前从未见过:inner-html.prop,但它非常适合我的项目。很好的答案。谢谢!
  • 请注意,不使用v-html 会影响 SSR(服务器端渲染)。在我的 Nuxt 项目中,静态生成无法显示内容。我切换到使用计算字段而不是使用过滤器。
  • 很高兴听到.prop 修饰符也用于v-bind!看起来 Vue 团队在 2.6 link 中添加了它的简写版本,但它导致了一些错误 link。一旦解决了这些问题,它将是 .inner-html 而不是 :inner-html.prop,这似乎更方便,并且与 v-bind 简写匹配。
  • 不错的答案..帮了我很多忙。谢谢?
【解决方案2】:

正如@acdcjunior 指出的那样,对我来说,这很有效:

<p v-html="$options.filters.json(description)"></p>

除此之外,我还应用了两个过滤器,而且它也有效:

<p v-html="$options.filters.filter1($options.filters.filter2(description))"></p>

【讨论】:

    【解决方案3】:

    问题是您的 HTML 是在过滤器添加到您的 Vue 实例之前处理的。试试这样: JSFiddle

    var jsonFormatter = function(json){
        if( typeof json!='string' ) json = JSON.stringify( json, null, 2 );
        json = json.replace( /</g, '&lt;' ).replace( />/g, '&gt;' ); // replace(/&/g, '&amp;')
        var pattern = /("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g;
        var html = json.replace( pattern, function( match ) {
            var cls = 'number';
            var suffix = '';
            if( /^"/.test( match ) ) {
                if( /:$/.test( match ) ) {
                    cls = 'key';
                    match = match.slice( 0, -1 );
                    suffix = ':'
                } else {
                    cls = 'string';
                }
            } else if( /true|false/.test( match ) ) {
                cls = 'boolean';
            } else if( /null/.test( match ) ) {
                cls = 'null';
            }
            return '<span class="' + cls + '">' + match + '</span>' + suffix;
        } );
        return html;
    }
    
    new Vue({
        el: '#app',
        data(){
            return {
            	jsonData: {dog: 'woof', nestedObject: {cat: 'meow'}}
            }
        },
        filters: {
        	jsonFormatter: jsonFormatter
        }
    });
    //Vue.filter( 'jsonFormatter', jsonFormatter ); // Doesn't work becuase happens after html is processed
    <div id="app" class="container">
         <h1>
            v-html directive
        </h1>
        <div v-html="this.$options.filters.jsonFormatter(jsonData)"></div>
    </div>

    【讨论】:

      【解决方案4】:

      如果你只是显示数据然后创建一个方法:

      json(jsonable) {
         return jsonedValue;
      }
      

      然后在html中

      <div v-html="json(mydata)"></div>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-13
        • 2013-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-01
        • 2018-03-17
        • 1970-01-01
        相关资源
        最近更新 更多