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!
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' } // 步进器 ]
Saya ingin mendapatkan komponen yang sepadan dengan pemaparan tag
dengan menggelungkan arr.
Mari analisa cara menulis secara optimum.
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.
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>
Protagonis hari ini, JSX, dijemput untuk muncul.
Komponen induk
const arr = [ { tag: 'van-field' }, // 输入框 { tag: 'van-cell' }, // 弹出层 { tag: 'van-stepper' } // 步进器 ]
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: '请输入姓名', "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>
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
Kami menggunakan komponen biasa, yang tidak boleh dijadikan apa yang kami mahu seperti komponen JSX.
Di siniv-model
Perangkap 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.
Mengambil kesempatan daripada permintaan ini, kami akan menebus JSX.
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);
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> ); } };
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> ); } };
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='custom-div'>这是自定义的DOM</div>"> </HelloWorld>
Kod komponen:
export default { name: "HelloWorld", props: { msg: String }, data() { return {}; }, methods: {}, render() { return <div domPropsInnerHTML={this.msg}></div>; } };
Hasil DOM yang diberikan:
v-untuk
Gunakan map
untuk melaksanakan:
render() { const list = [1,2,3] return( <div> { list.map(item => <button>按钮{item}</button>) } </div> ) }
v-jika
Contoh mudah: gunakan tiga Meta
render() { const bool = false; return <div>{bool ? <button>按钮1</button> : <button>按钮2</button>}</div>; }
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> ) } }
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> ); } };
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> ); } };
用监听事件来实现v-model
:
methods: { input(e) { this.value = e.target.value; } }, render() { return ( <div> <input type="text" value={this.value} onInput={this.input} /> </div> ); }
也可以调整为:
<input type="text" value={this.value} onInput={(e) => (this.vaue = e.target.value)} />
还可以使用对象的方式去监听事件:解构事件
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> ); } };
nativeOn
仅对于组件,用于监听原生事件,也可以使用对象的方式去监听事件:
{...{nativeOn:{click: this.handleClick}}}
事件修饰符
和指令一样,除了个别的之外,大部分的事件修饰符都无法在JSX中使用。
event.stopPropagation()
来代替event.preventDefault()
来代替if (event.target !== event.currentTarget){ return }
.enter与keyCode
: 在特定键触发时才触发回调
if(event.keyCode === 13) { // 执行逻辑 }
除了上面这些修饰符之外,尤大大对于.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> ); } };
父传子。
示例:
<HelloWorld> <template slot="default">默认内容</template> <template slot="footer"> <el-button type="primary">确定</el-button> <el-button>取消</el-button> </template> </HelloWorld>
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> ); } };
子传父。
示例:
<HelloWorld> <template v-slot:content="{ name, age }"> <div>姓名:{{ name }}</div> <div>年龄:{{ age }}</div> </template> </HelloWorld>
HelloWorld组件代码:this.$scopedSlots
export default { name: "HelloWorld", render() { return ( <div> <div class="content">{this.$scopedSlots.content({ name: "张三", age: 20 })}</div> </div> ); } };
子组件通过{this.$scopedSlots.content({ name: "张三", age: 20 })}
指定插槽的名称为content
,并将含有name,age属性的对象数据传递给父组件,父组件就可以在插槽内容中使用子组件传递来的数据。
看到v-html用innerHTML;v-for用map;.stop用
event.stopPropagation()
。
你有什么感想?
这不就是我们JavaScript方法的操作吗。
所以JSX就是Javascript + XML。
我以前一直觉得Vue中没必要用JSX吧,用模板Template足以了。
但经过这个需求,我想JSX在处理动态渲染组件还是蛮占有优势的?。
日后面试官问我JSX在Vue的有什么应用场景,我想我可以把这个需求说一说。
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!