Vue-cli If you have used VUE, I think you all know how the XXx. vue component works. How to render template,script,style to the page? Today we manually wrote a simple Vue component online editor to play around with.

Let’s take a look at the effect without saying more

The preparatory work

  1. Install vuejs

  2. New XXX. HTML

  3. New XXX. CSS

Write a page

  <div id="app">
        <textarea name="" id="" cols="30" rows="30" v-model="content" autofocus placeholder="Please enter vue template"></textarea>
        <div class="btn-center">
            <button @click="run">Run the code</button>
            <button @click="reset">remove</button>
        </div>
    </div>
    <div id="result"></div>
    <script src="./node_modules/vue/dist/vue.js"></script>
Copy the code

The Textarea element is the authoring part of the VUE component code, and the button is the button area

textarea {
            display: block;
            width: 100%;
            min-height: 100px;
            max-height: 500px;
            padding: 8px;
            resize: auto;
 }

 button {
            margin-top: 8px;
            display: inline-block;
            padding: 5px 16px;
            font-size: 14px;
            font-weight: 500;
            line-height: 20px;
            white-space: nowrap;
            vertical-align: middle;
            cursor: pointer;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
            border: 1px solid;
            border-radius: 6px;
            -webkit-appearance: none;
            -moz-appearance: none;
            appearance: none;
}
 .btn-center{
           text-align: center;
 }
Copy the code

Decomposition of thinking

In XXx. vue, we usually write components following a template

<template>
    
</template>
<script>
export default{}</script>
<style>

</style>
Copy the code

The idea is that after we get the input, we want to get the tempalte,script,style content and then mount it to the page elements using the Vue. Extend (options) method.

Parsing the label

We need to get the content including the part outside the red circle in the figure below

The match method of the string can be used to obtain the subscript of the start tag, the length of the start tag, and the subscript of the end tag of each segment, and then the desired content can be intercepted by slice method.

             getSource(type){
                   const reg = new RegExp(` <${type}[^ >] * > `);
                   let content = this.content;
                   let matches = content.match(reg);
                   if(matches){
                       let start = content.indexOf(matches[0])+matches[0].length;
                       let end = content.lastIndexOf(` < /${type}`);
                       return content.slice(start,end)
                   }
                },
Copy the code

The result obtained after interception

Transformation function

In the vue official website,data must be a function, we get a string

export default {
    data(){
        return {
            msg:'hello world'}},methods: {run(){
            console.log("Hello")}}}Copy the code

How to convert a string into an executable function, see how to execute a string?

We can use the new Function method to convert a string into an executable Function, and what we need is

data(){
        return {
            msg:'hello world'}},methods: {run(){
            console.log("Hello")}}Copy the code

Use the string replace method to replace export default with return

Complete code

              run:function(){
                    let template = this.getSource("template");
                    if(! template)return
                    let script = this.getSource("script");
                    if(script){
                        script = script.replace(/export default/."return");
                    }
                    let obj = new Function(script)();
                    obj.template = template;
                    let Profile = Vue.extend(obj);
                    new Profile().$mount("#result")},Copy the code

Processing style

After retrieving the style from the re parsing, add it to the head

let styleCss = this.getSource("style");
let style = document.createElement("style");
style.innerHTML = styleCss;
document.head.appendChild(style);
Copy the code

conclusion

That’s all for this article, a simple Vue component online editor implemented simply with the vue.extend () method

    <div id="app">
        <textarea name="" id="" cols="30" rows="30" v-model="content" autofocus placeholder="Please enter vue template"></textarea>
        <div class="btn-center">
            <button @click="run">Run the code</button>
            <button @click="reset">remove</button>
        </div>
    </div>
    <div id="result"></div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        new Vue({
            el: "#app".data() {
                return {
                    content: ""}},methods: {
                getSource(type) {
                    const reg = new RegExp(` <${type}[^ >] * > `);
                    let content = this.content;
                    let matches = content.match(reg);
                    if (matches) {
                        let start = content.indexOf(matches[0]) + matches[0].length;
                        let end = content.lastIndexOf(` < /${type}`);
                        console.log(content.slice(start, end));
                        return content.slice(start, end)
                    }
                },
                run: function () {
                    let template = this.getSource("template");
                    if(! template)return
                    let script = this.getSource("script");
                    if (script) {
                        script = script.replace(/export default/."return");
                    }
                    let styleCss = this.getSource("style");
                    let style = document.createElement("style");
                    style.innerHTML = styleCss;
                    document.head.appendChild(style);
                    let obj = new Function(script)();
                    obj.template = template;
                    let Profile = Vue.extend(obj);
                    new Profile().$mount("#result")},reset() {
                    this.content = ' '}}})</script>
Copy the code

Like a like, thank you for your support, more articles public number front-end briefing welcome to visit