2016-11-13 26 views
5

Tôi có một hình thức trong một khu vực quản trị mà người dùng có thể nhập văn bản với shortcodes trong đó:động tiêm Vue 2 thành phần từ shortcode

lò nhiệt tại [tạm c = 200]

gì Tôi muốn là temp mã ngắn để được phân tích cú pháp và chuyển thành thành phần Vue 2 khi được hiển thị trong giao diện người dùng.

Dưới đây là một đơn giản Temperature.vue thành phần:

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

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

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

Và đây là một Instructions.vue thành phần đơn giản mà sẽ phân tích và đưa ra các văn bản với shortcodes:

<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> 

Các phân tích hoạt động tốt, và sự thay thế được in trong giao diện người dùng. Nhưng thẻ <temperature> được hiển thị theo nghĩa đen chứ không phải là thành phần Vue, phần nào được mong đợi.

lò nhiệt ở nhiệt độ <: C = "200"> </nhiệt độ>

Những gì tôi dường như không thể quấn quanh đầu tôi là những gì bước tôi nên đưa cho nó để thực sự chuyển đổi vào thành phần Temperature mà tôi đã xác định. Thậm chí có thể không? Có cách nào chính thống hơn để làm điều này mà tôi đang thiếu?

Ngoài ra còn có mối quan ngại về bảo mật khi sử dụng v-html để hiển thị văn bản. Tôi không nhất thiết muốn điều này được ở đó, nhưng tôi đoán nó thậm chí còn xa vời hơn để mong đợi các thành phần Temperature xuất hiện từ một chuỗi thoát. Tôi luôn có thể khử trùng trước khi chèn vào cơ sở dữ liệu, nhưng tôi vẫn muốn tránh v-html nếu có thể.

Trả lời

4

Để làm ví dụ, bạn cần sử dụng hàm render của thành phần Hướng dẫn. Trong hàm render, bạn có thể tạo một thành phần Vue mới, cho phép nói 'intruction', mà bạn sẽ truyền chuỗi kết quả từ phân tích cú pháp shortcode để sử dụng làm mẫu. Trong khai báo thành phần đó, bạn sẽ nối thêm thành phần Temperature (Nhiệt độ) như một đứa trẻ và nó sẽ tạo ra sự chống đỡ mà bạn đã vượt qua. Và đó là nó. Ví dụ sau:

Instructions.vue Code-khôn ngoan

<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

Tuyệt, tôi thích cách tiếp cận này. Không xa những gì tôi có, thực sự ... Tôi sẽ kiểm tra nó càng sớm càng tốt và cho bạn biết! –

0

Hiện tại không có bước nào để bạn biên soạn mẫu đó là lý do tại sao nó được hiển thị dưới dạng văn bản. Tôi nghĩ rằng bạn có thể làm như sau để thay thế văn bản với các thành phần

  1. Khi bạn tìm ra nhiệt độ quấn nó trong phần tử html
  2. Tạo dụ Vue mới trong JavaScript (không phải là mẫu html trong string)
  3. Núi vue Ví dụ trên đỉnh của nguyên tố rằng việc sử dụng tùy chọn el hoặc $ mount
  4. sử dụng phép nội suy thay vì v-html để ngăn ngừa XSS https://vuejs.org/v2/guide/syntax.html#Text
+0

thế nào sẽ có cái nhìn trong ví dụ tôi đưa? –

2

đây là cách tiếp cận của tôi, không chắc chắn nếu nó là gì y ou là sau. Nó giới thiệu một thành phần trung gian để hiển thị nội dung động. Ngoài ra, tôi sửa đổi Instructions.vue một chút để thử nghiệm của tôi, bạn có thể sửa đổi để phù hợp với phân tích cú pháp shortcode của bạn

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

Một cách tiếp cận rất thú vị và trông khá sạch sẽ. Tôi sẽ kiểm tra nó ngay sau khi tôi có cơ hội và sẽ lấy lại cho bạn. –

Các vấn đề liên quan