Rumah > hujung hadapan web > View.js > teks badan

Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX

青灯夜游
Lepaskan: 2022-12-05 18:53:43
ke hadapan
2933 orang telah melayarinya

Bagaimanakah Vue memaparkan komponen secara dinamik melalui JSX? Artikel berikut akan memperkenalkan kepada anda cara untuk menghasilkan komponen secara dinamik secara cekap melalui JSX dalam Vue saya harap ia akan membantu anda!

Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX

1. Keperluan yang jelas

Bagaimana untuk memaparkan komponen dinamik? [Cadangan berkaitan: tutorial video vuejs]

mempunyai set struktur tatasusunan seperti berikut:

const arr = [ 
  { tag: 'van-field' },  // 输入框
  { tag: 'van-cell' },   // 弹出层
  { tag: 'van-stepper' } // 步进器
]
Salin selepas log masuk

Saya ingin mendapatkan komponen yang sepadan dengan pemaparan tag dengan menggelungkan arr.

Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX

Mari analisa cara menulis secara optimum.

2. Analisis

2.1 v-if Zou Tianxia

Kita boleh menulis v-for tatasusunan arr gelung , dan kemudian gunakan v-if untuk menentukan teg dan menghasilkan jenis komponen yang sepadan.

Bukan mustahil untuk menulis seperti ini, tetapi skalabilitasnya tidak bagus Setiap kali teg ditambah, v-if mesti ditambah pada templat.

Saya percaya ramai yang menulis begini pada mulanya.

Tetapi ini bukan kod yang patut kita tulis oleh orang yang elegan.

2.2 Memaparkan label komponen secara dinamik

Bolehkah kami memberikan label sebenar berdasarkan label tag.

Kuncinya ialah cara untuk memaparkan komponen sebenar berdasarkan teg yang dilalui dalam gelung.

<van-cell  v-for="(cell, cellKey) in arr" :key="cellKey" >
      <!-- 动态渲染  -->
</van-cell>
Salin selepas log masuk

Protagonis hari ini, JSX, dijemput untuk muncul.

Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX

2.3 Komponen pemaparan dinamik JSX

Komponen induk


  
  


const arr = [ 
  { tag: &#39;van-field&#39; },  // 输入框
  { tag: &#39;van-cell&#39; },   // 弹出层
  { tag: &#39;van-stepper&#39; } // 步进器
]
Salin selepas log masuk

Komponen anak RendTag.vue

<script>
const AssemblyRend = {
  name: "assembly-rend",
  props: ["cell"],
  data() {
    return {
      input: "",
    };
  },
  methods: {
    onClick() {
      this.$emit("changeTag", this.input);
    },
  },
  computed:{
    itemVal:{
      get(){
        return this.cell.value
      },
      set(v){
        this.cell.value = v
      }
    }
  },
  render() {
    const { cell } = this; // 解构
    const assembly = cell.tag;  // 这里就是我们动态渲染组件的核心 

    return (
        <assembly
          v-model={this.itemVal}
          placeholder={cell.placeholder}
          min={cell.min}
          onClick={this.onClick}
        >
        </assembly>
      );
  },
};

export default {
  name: "RendTag",
  props: {
    cell: {
        type: Object,
        default:()=>{
            return {
                {
                    "title": "能否输入",
                    placeholder: &#39;请输入姓名&#39;,
                    "value": "name",
                    "tag": "van-switch",
                }
            }
        }
    },
  },
  methods: {
    changeTag(val) {},
  },
  render() {
    const { cell } = this; // 解构
    return (
      <div class="rendTag-content">
        <AssemblyRend
          cell={cell}
          onChangeTag={this.changeTag}
        ></AssemblyRend>
      </div>
    );
  },
};
</script>
Salin selepas log masuk

Kami boleh menggunakan render JSX untuk menulis komponen pulangan JavaScript untuk mencapai pemaparan dinamik kami bagi teg.

render adalah bersamaan dengan templat dalam vue kami.

Jadi kesan pemaparan adalah seperti berikut: dijadikan komponen sebenar mengikut tag

Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX

Kami menggunakan komponen biasa, yang tidak boleh dijadikan apa yang kami mahu seperti komponen JSX.

Di siniv-modelPerangkap menggunakan atribut yang dikira, saya syorkan membacanya:Cara untuk mengikat ungkapan berbilang gelung dalam model v praktikal (termasuk prinsip)

Sebenarnya, kedua-dua artikel ini dikaitkan pada tahap tertentu, tetapi saya telah memisahkan keperluan di sini.

Terutama untuk memudahkan pembacaan dan pemahaman rakan-rakan.

3. Cara menggunakan JSX dalam vue

Mengambil kesempatan daripada permintaan ini, kami akan menebus JSX.

3.1 Apakah itu?

JSX ialah sambungan sintaks Javascript, JSX = Javascript + XML, yang bermaksud menulis XML dalam Javascript, kerana ciri JSX ini, ia mempunyai fleksibiliti Javascript dan kefungsian html .

Sesetengah komponen dengan aktiviti yang kuat boleh digantikan oleh JSX (seperti keperluan di atas
Tidak perlu menggunakan JSX untuk keseluruhan projek);

3.2 Penggunaan asas

3.2.1 Komponen berfungsi

Kami juga boleh membenamkan komponen ButtonCounter.

const ButtonCounter = {
  name: "button-counter",
  props: ["count"],
  methods: {
    onClick() {
      this.$emit("changeNum", this.count + 1);
    }
  },
  render() {
    return <button onClick={this.onClick}>数量:{this.count}</button>;
  }
};

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      count: 0
    };
  },
  methods: {
    // 改变button按钮数量
    changeNum(val) {
      this.count = val;
    }
  },
  render() {
    const { count } = this; // 解构
    return (
      <div class="hello-world-content">
        <ButtonCounter style={{ marginTop: "20px" }} count={count} onChangeNum={this.changeNum}></ButtonCounter>
      </div>
    );
  }
};
Salin selepas log masuk

3.2.2 Atribut biasa, gaya sebaris, kelas dinamik dan gaya

Seperti yang anda lihat, ia pada asasnya sama dengan kaedah penulisan templat vue, kecuali ia perlu Beri perhatian kepada pendakap kerinting;

memerlukan dua pasang pendakap kerinting dalam templat vue, manakala JSX hanya perlu menulis sepasang dan .

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      count: 0,
      text: "Hello World!",
      msgClass: "msg-class",
      isGreen: true
    };
  },
  render() {
    const { count, text } = this; // 解构
    return (
      <div class="hello-world-content">
        <p class={this.msg ? this.msgClass : ""}>动态绑定class</p>
        <p style={this.isGreen ? "color: green" : ""}>动态绑定style</p>
      </div>
    );
  }
};
Salin selepas log masuk

Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX

3.2.3 Perintah biasa

v-html, v-if, v-for, v-model Arahan biasa tidak boleh digunakan dalam JSX dan perlu dilaksanakan dengan cara lain.

v-html

Dalam JSX, jika anda ingin menetapkan innerHTML DOM, anda perlu menggunakan domProps.

Penggunaan komponen:

<HelloWorld 
   msg="<div class=&#39;custom-div&#39;>这是自定义的DOM</div>"> 
</HelloWorld>
Salin selepas log masuk

Kod komponen:

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {};
  },
  methods: {},
  render() {
    return <div domPropsInnerHTML={this.msg}></div>;
  }
};
Salin selepas log masuk

Hasil DOM yang diberikan:

Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX

v-untuk

Gunakan map untuk melaksanakan:

render() {
  const list = [1,2,3]
  return( 
    <div>
      { list.map(item => <button>按钮{item}</button>) }
    </div>
  )
}
Salin selepas log masuk

v-jika

Contoh mudah: gunakan tiga Meta

render() {
    const bool = false;
    return <div>{bool ? <button>按钮1</button> : <button>按钮2</button>}</div>;
}
Salin selepas log masuk

Contoh kompleks: terus gunakan JS

render() {
  let num = 3
  if(num === 1){ return( <button>按钮1</button> ) }
  if(num === 2){ return( <button>按钮2</button> ) }
  if(num === 3){ return( <button>按钮3</button> ) }
}
Salin selepas log masuk

v-model

Gunakan terus: <input v-model={this.value}>

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      value: "abc"
    };
  },
  watch: {
    value(val) {
      console.log("this.model内容:" + val);
    }
  },
  methods: {},
  render() {
    return (
      <div>
        <input v-model={this.value} placeholder="普通文本" />
      </div>
    );
  }
};
Salin selepas log masuk

3.2.4 Mendengar acara dan pengubah suai acara

Mendengar acara

Saya terfikir untuk menggunakan onChange, onClick, dll. untuk mendengar acara.

需要注意的是,传参数不能使用 onClick={this.handleClick(params)},这样子会每次 render的时候都会自动执行一次方法。

应该使用bind,或者箭头函数来传参。

组件示例代码:

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {};
  },
  methods: {
    handleClick(val) {
      alert(val);
    }
  },
  render() {
    return (
      <div>
        <button type="button" onClick={this.handleClick.bind(this, 11)}>
          方式一
        </button>
        <button type="button" onClick={() => this.handleClick(22)}>
          方式二
        </button>
      </div>
    );
  }
};
Salin selepas log masuk

用监听事件来实现v-model:

methods: {
    input(e) {
      this.value = e.target.value;
    }
  },
  render() {
    return (
      <div>
        <input type="text" value={this.value} onInput={this.input} />
      </div>
    );
  }
Salin selepas log masuk

也可以调整为:

<input 
  type="text" 
  value={this.value} 
  onInput={(e) => (this.vaue = e.target.value)} 
/>
Salin selepas log masuk

还可以使用对象的方式去监听事件:解构事件

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  data() {
    return {
      value: ""
    };
  },
  watch: {
    value(val) {
      console.log("this.model的内容:" + val);
    }
  },
  methods: {
    handleInput(e) {
      this.value = e.target.value;
    },
    handleFocus(e) {
      console.log(e.target);
    }
  },
  render() {
    return (
      <div>
        <input type="text" value={this.value} {...{ on: { input: this.handleInput, focus: this.handleFocus } }} />
      </div>
    );
  }
};
Salin selepas log masuk

nativeOn仅对于组件,用于监听原生事件,也可以使用对象的方式去监听事件:

{...{nativeOn:{click: this.handleClick}}}
Salin selepas log masuk

事件修饰符

和指令一样,除了个别的之外,大部分的事件修饰符都无法在JSX中使用。

  • .stop : 阻止事件冒泡,在JSX中使用event.stopPropagation()来代替
  • .prevent:阻止默认行为,在JSX中使用event.preventDefault() 来代替
  • .self:只当事件是从侦听器绑定的元素本身触发时才触发回调,使用下面的条件判断进行代替
if (event.target !== event.currentTarget){
  return
}
Salin selepas log masuk

.enter与keyCode: 在特定键触发时才触发回调

if(event.keyCode === 13) {
  // 执行逻辑
}
Salin selepas log masuk

除了上面这些修饰符之外,尤大大对于.once,.capture,.passive,.capture.once做了优化,简化代码:

export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  methods: {
    handleClick(e) {
      console.log("click事件:" + e.target);
    },
    handleInput(e) {
      console.log("input事件:" + e.target);
    },
    handleMouseDown(e) {
      console.log("mousedown事件:" + e.target);
    },
    handleMouseUp(e) {
      console.log("mouseup事件" + e.target);
    }
  },
  render() {
    return (
      <div
        {...{
          on: {
            // 相当于 :click.capture
            "!click": this.handleClick,
            // 相当于 :input.once
            "~input": this.handleInput,
            // 相当于 :mousedown.passive
            "&mousedown": this.handleMouseDown,
            // 相当于 :mouseup.capture.once
            "~!mouseup": this.handleMouseUp
          }
        }}
      >
        点击模块
      </div>
    );
  }
};
Salin selepas log masuk

3.3 插槽

3.3.1 普通插槽与具名插槽

父传子。

示例:

<HelloWorld>
    <template slot="default">默认内容</template>
    <template slot="footer">
      <el-button type="primary">确定</el-button>
      <el-button>取消</el-button>
    </template>
</HelloWorld>
Salin selepas log masuk

HelloWorld组件代码:this.$slots

export default {
  name: "HelloWorld",
  render() {
    return (
      <div>
        <div class="default">{this.$slots.default}</div>
        <div class="footer">{this.$slots.footer}</div>
      </div>
    );
  }
};
Salin selepas log masuk

3.3.2 作用域插槽

子传父。

示例:

<HelloWorld>
    <template v-slot:content="{ name, age }">
      <div>姓名:{{ name }}</div>
      <div>年龄:{{ age }}</div>
    </template>
</HelloWorld>
Salin selepas log masuk

HelloWorld组件代码:this.$scopedSlots

export default {
  name: "HelloWorld",
  render() {
    return (
      <div>
        <div class="content">{this.$scopedSlots.content({ name: "张三", age: 20 })}</div>
      </div>
    );
  }
};
Salin selepas log masuk

子组件通过{this.$scopedSlots.content({ name: "张三", age: 20 })}指定插槽的名称为content,并将含有name,age属性的对象数据传递给父组件,父组件就可以在插槽内容中使用子组件传递来的数据。

看到v-html用innerHTML;v-for用map;.stop用event.stopPropagation()
你有什么感想?
这不就是我们JavaScript方法的操作吗。
所以JSX就是Javascript + XML。

Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX

后记

我以前一直觉得Vue中没必要用JSX吧,用模板Template足以了。

但经过这个需求,我想JSX在处理动态渲染组件还是蛮占有优势的?。

日后面试官问我JSX在Vue的有什么应用场景,我想我可以把这个需求说一说。

(学习视频分享:web前端开发编程基础视频

Atas ialah kandungan terperinci Mari kita bincangkan tentang cara Vue memaparkan komponen secara dinamik melalui JSX. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan