2016-11-13 71 views
5

注入Vue的2組分I有一個表格在管理區,其中用戶可以與簡碼輸入文本在它們:動態地從短碼

熱烘箱中於[溫度℃= 200]

什麼我想要的是temp短碼可以在前端顯示時被解析並轉換成Vue 2組件。

這裏有一個簡單的Temperature.vue組件:

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

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

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

而且這裏有一個簡單的Instructions.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> 

解析工作正常,並打印替代在前端。但<temperature>標籤是逐字呈現的,而不是Vue組件,這是有點期待的。在<溫度

烤箱預熱:攝氏度=「200」> < /溫度>

似乎我不能換行我的頭周圍是我應該採取什麼樣的步驟,其實際轉換進入我已經定義的Temperature組件。它甚至有可能嗎?有沒有更正統的做法,我失蹤了?

使用v-html來呈現文本也存在安全問題。我不一定要這樣做,但我猜測它更加遙遠,以期望Temperature組件從一個轉義字符串中出現。我可以在插入數據庫之前始終進行清理,但如果可能的話,我仍然希望避免v-html

回答

4

爲了使你的工作,例如,您需要使用您的指示組件的渲染功能。在渲染函數中,您可以創建一個新的Vue組件,讓我們說'intruction',您將傳遞由shortcode parse產生的字符串作爲模板。在該組件聲明中,您將添加溫度組件作爲一個孩子,它會呈現您已經通過的道具。就是這樣。該示例如下:

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

目前沒有模板編譯的步驟,這就是爲什麼它被呈現爲文本。我覺得你可以做以下的有分量

  1. 替換文本一旦你找到了溫敷在html元素
  2. 在JavaScript中創建新的Vue實例(而不是字符串HTML模板)
  3. 山VUE例如在該元素的使用EL選項或頂部$安裝
  4. 使用插值,而不是v-HTML,以防止XSS https://vuejs.org/v2/guide/syntax.html#Text
+0

代碼明智怎麼會那樣子的例子中,我給了? –

2

這裏是我的方法,不知道它是什麼ÿ你在之後。它引入了一箇中間組件來動態渲染東西。另外,我修改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

一個非常有趣的方法,看起來很乾淨。一旦我有機會,我會盡快進行測試,並會盡快回復您。 –