programing

쇼트 코드에서 Vue 2 컴포넌트를 동적으로 주입합니다.

prostudy 2022. 6. 11. 11:47
반응형

쇼트 코드에서 Vue 2 컴포넌트를 동적으로 주입합니다.

사용자가 쇼트 코드를 포함한 텍스트를 입력할 수 있는 폼이 관리 영역에 있습니다.

오븐을 [125 c=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 컴포넌트가 아닌 문자 그대로 렌더링됩니다.이것은 어느 정도 예상되고 있습니다.

오븐을 <온도:420="200"><온도>로 가열

머리를 싸매지 못할 것 같은 것은 실제로 변모하기 위해 어떤 단계를 밟아야 하는가 하는 것입니다.Temperature컴포넌트를 정의합니다.그게 가능하기나 해?제가 놓치고 있는 더 정통적인 방법이 있을까요?

또한 보안상의 문제가 있습니다.v-html텍스트를 렌더링합니다.이게 꼭 거기 있는 건 아니지만, 내 생각엔 더 이상 기대하기 힘들 것 같아.Temperature이스케이프된 문자열에서 표시되는 컴포넌트.데이터베이스에 삽입하기 전에 언제든지 데이터를 삭제할 수 있지만, 그래도 삭제는 피하고 싶다.v-html가능하다면

예를 사용하려면 명령 구성요소의 렌더링 기능을 사용해야 합니다.렌더 함수에서는 새로운 Vue 컴포넌트(예를 들어 'instruction')를 작성할 수 있습니다.이것에 쇼트 코드 해석의 결과 문자열을 전달해 템플릿으로 사용할 수 있습니다.이 컴포넌트 선언에서는 Temperature 컴포넌트를 아이로 추가하여 통과한 프로포넌트를 렌더링합니다.그리고 이것이 마지막입니다.예를 다음에 나타냅니다.

지침들.표시하다

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

이게 내 접근법이야. 그게 네가 원하는 건지 확실하지 않아.중간 컴포넌트를 도입하여 동적으로 렌더링합니다.또한, 저는 설명서를 수정했습니다.테스트를 위해 약간의 수정이 가능하며 쇼트 코드 파서에 맞게 수정할 수 있습니다.

지침들.표시하다

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

다이나믹 컴포넌트표시하다

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

현재 템플릿을 컴파일하는 단계가 없으므로 템플릿이 텍스트로 렌더링됩니다.텍스트를 컴포넌트로 대체하려면 다음과 같이 하십시오.

  1. 온도를 찾으면 html 요소로 랩합니다.
  2. JavaScript에서 새 Vue 인스턴스 생성(문자열의 html 템플릿이 아님)
  3. el 옵션 또는 $mount를 사용하여 해당 요소의 상단에 vue 인스턴스를 마운트합니다.
  4. XSS https://vuejs.org/v2/guide/syntax.html#Text를 방지하려면 v-module 대신 보간 사용

언급URL : https://stackoverflow.com/questions/40573011/dynamically-inject-vue-2-component-from-shortcode

반응형