web-dev-qa-db-ja.com

フィルタ付きのVueJS2v-html

フィルタを使用して生の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でこれを行う正しい方法は何ですか?

9
Kokizzu

完全を期すために、次のようないくつかのオプションがあります。

  • 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>_
19
acdcjunior

問題は、フィルターがVueインスタンスに追加される前にHTMLが処理されることです。次のようにしてください: 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>
5
BSSchwarzkopf

私にとって、@ acdcjuniorが指摘したように、これはうまくいきました:

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

それ以外に、適用する2つのフィルターがあり、それも機能しました。

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

データを表示するだけの場合は、メソッドを作成します。

json(jsonable) {
   return jsonedValue;
}

その後、htmlで

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