2016-11-13 4 views
5

からVueの2成分を注入:[一時C = 200]動的私はそれらにショートコードを持つユーザーができる入力テキスト管理エリアのフォーム有するショート

何で

熱オーブン私は、フロントエンドに表示されたときにtempショートコードが解析され、Vue 2コンポーネントに変換されることを望みます。

ここでは単純化されたTemperature.vueコンポーネントです:

<template> 
    <div v-html="parseShortcodes(text)"></div> 
</template> 

<script> 
    import ShortcodeParser from 'meta-shortcodes' 
    import Temperature from 'Temperature.vue' 

    export default { 

     data:() => { 
      return { 
       text: 'Heat oven at [temp c=200]', 
       parser: ShortcodeParser() 
      } 
     }, 
     components: [ 
      Temperature 
     ], 
     methods: { 
      parseShortcodes(text) { 
       return this.parser.parse(text) 
      } 
     }, 
     created() { 
      this.parser.add('temp', function(options) { 
       return '<temperature :celsius="'+options.c+'"></temperature>' 
      }) 
     } 
    } 
</script> 

解析が正常に動作し、かつ置換が印刷されています

<template> 
    <span class="temperature"> 
     {{ celsius }}&deg;C 
    </span> 
</template> 

<script> 
    import { mapGetters, mapActions } from 'vuex' 

    export default { 
     props: ['celsius'], 
     name: 'temperature' 
    } 
</script> 

そして、ここでは、ショートコードとテキストを解析し、レンダリングします簡略化Instructions.vueコンポーネントですが、フロントエンドでしかし、<temperature>タグは、Vueコンポーネントとしてではなく文字通りにレンダリングされます。 <温度で

熱オーブン:摂氏=「200」>私の周り私の頭をラップすることができないよう何< /温度>

は、それが実際に変換するために私が取るべきステップです私が定義したTemperatureコンポーネントに入れます。それも可能ですか?私が行方不明になっているより正統な方法がありますか?

v-htmlを使用してテキストをレンダリングすることのセキュリティ上の懸念もあります。私は必ずしもこれがそこに存在するとは思っていませんが、私は、それがさらにエスケープされた文字列からTemperatureコンポーネントが現れることを期待するためにはるかに遠いと思っています。私はデータベースに挿入する前にいつでも消毒することができますが、可能であれば、私はまだv-htmlを避けたいと思います。

答えて

4

はあなたの命令コンポーネントのレンダリング機能を使用する必要があります動作します。レンダリング機能では、新しいVueコンポーネントを作成して、 'intruction'と言うことができます。これには、短文解析の結果として得られた文字列をテンプレートとして渡すことができます。そのコンポーネント宣言では、子としてTemperatureコンポーネントを追加し、渡した小道具をレンダリングします。以上です。例は次のとおりです。

Instructions.vue

<script> 
    import ShortcodeParser from 'meta-shortcodes' 
    import Temperature from 'Temperature.vue' 

    export default { 

     data:() => { 
      return { 
       text: 'Heat oven at [temp c=200]', 
       parser: ShortcodeParser() 
      } 
     }, 
     methods: { 
      parseShortcodes(text) { 
       return this.parser.parse(text) 
      } 
     }, 
     render (createElement) { 

      const template = this.parseShortcodes(this.text) //returns something like this <div class="intruction">'Heat oven at <temperature :celsius="200"></temperature>'</div> 

      var component = Vue.component('instruction', { 
       template: template, 
       components: { 
        'temperature': Temperature 
       } 
      }) 

      return createElement(
       'div', 
       { 
        class: { 
         instructions: true 
        } 
       }, 
       [ 
        createElement(component) 
       ] 
      ) 
     } 
    } 
</script> 
+0

クール、私はこのアプローチが好きです。私の持っているものから遠くない、本当に...私はできるだけ早くテストしてお知らせします! –

0

現在、テンプレートがコンパイルされているため、テキストとしてレンダリングされています。私はあなたが、温度が

  • はJavaScriptで新しいVueのインスタンスを作成し、HTML要素でラップ見つけたら部品

    1. でテキストを交換するには、次の何ができると思います
    2. マウントVUE(ない文字列のHTMLテンプレートなど)それはどのようなYの場合エル・オプションまたは$ここでXSS https://vuejs.org/v2/guide/syntax.html#Text
  • +0

    コードワイズどのようにそれは私が与えた例に見えるのでしょうか? –

    2

    を防ぐために

  • 使用補間の代わりに、V-HTMLをマウントを使用して、その要素の上のインスタンスは、必ず私のアプローチではありませんああ後です。物を動的にレンダリングするための中間コンポーネントを紹介します。また、私はInstructions.vue私のテストのためのビットを変更し、あなたのショートパーサ

    に合わせて変更することができますInstructions.vue

    <template> 
        <div> 
        <input type="text" @input="parseInput" /> 
        <DynamicComponent :type="parsedType" :props="parsedProps"></DynamicComponent> 
        </div> 
    </template> 
    
    <script> 
    import DynamicComponent from './DynamicComponent'; 
    
    
    export default { 
        components: { 
        DynamicComponent 
        }, 
        data() { 
        return { 
         parsedType: '', 
         parsedProps: '' 
        }; 
        }, 
        methods: { 
        parseInput(e) { // parse the input 
         if (e.target.value === '[temp c=200]') { // change this to use your parser 
         this.parsedType = 'Temperature'; 
         this.parsedProps = { celsius: 200 }; 
         } else { 
         this.parsedType = ''; 
         this.parsedProps = ''; 
         } 
        } 
        } 
    }; 
    </script> 
    

    DynamicComponent。あなたの例を作るためにVUE

    <script> 
    import Temperature from './Temperature'; 
    // import all other dynamically rendered components 
    
    
    export default { 
        components: { 
        // let it know what components are there 
        Temperature 
        }, 
        props: ['type', 'props'], 
        render(h) { 
        return h(this.type, { 
         props: this.props 
        }, this.$slots.default); 
        } 
    }; 
    </script> 
    
  • +0

    非常に興味深いアプローチで、きれいに見えます。私はチャンスを得るとすぐにそれを試し、あなたに戻ってきます。 –

    関連する問題