子组件补充
子组件案列
<!DOCTYPE html> <html lang="en"> <head> <meta charset='UTF-8'> <title>子组件案例</title> <style> .wrap { width: calc(200px * 4 + 80px); margin: 0 auto; user-select: none; } .box { width: 200px; height: 360px; /*border: 1px solid black;*/ background-color: rgba(10, 200, 30, 0.5); border-radius: 10px; float: left; margin: 10px; } .box img { width: 100%; /*height: 200px;*/ border-radius: 50%; /*width:10%;*/ /*height:15%;*/ float:right; /*margin-left:20px;*/ } .b1{ text-align: center; } </style> </head> <body> <div id="app"> <div class="wrap"></div> <my-tag1 ></my-tag1> <my-tag2 ></my-tag2> <my-tag3 ></my-tag3> <my-tag4 ></my-tag4> </div> </body> <script src="js/vue.js"></script> <script> let Title = { template: ` <p class="b1">前女友</p> ` }; let myTag1 = { template:` <div class="box"> <img src="img/111.jpg" alt=""> <Title></Title> <p class="b1" @click="fn">抱了{{ num }}次</p> </div> `, components: { Title }, data(){ return { num: 0 } }, methods:{ fn(){ this.num ++ } } }; let myTag2 = { template:` <div class="box"> <img src="img/222.jpg" alt=""> <Title></Title> <p class="b1" @click="fn">抱了{{ num }}次</p> </div> `, components:{ Title }, data(){ return { num: 0 } }, methods:{ fn(){ this.num ++ } } }; let myTag3 = { template:` <div class="box"> <img src="img/333.jpg" alt=""> <Title></Title> <p class="b1" @click="fn">抱了{{ num }}次</p> </div> `, components:{ Title }, data(){ return { num: 0 } }, methods:{ fn() { this.num ++ } } }; let myTag4 = { template:` <div class="box"> <img src="img/444.jpg" alt=""> <Title></Title> <p class="b1" @click="fn">抱了{{ num }}次</p> </div> `, components:{ Title }, data(){ return { num: 0 } }, methods:{ fn(){ this.num ++ } } }; new Vue({ el:'#app', components:{ myTag1, myTag2, myTag3, myTag4 } }) </script> </html>
案列二
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title></title> <style> .wrap { width: calc(200px * 4 + 80px); margin: 0 auto; user-select: none; } .box { width: 200px; height: 260px; /*border: 1px solid black;*/ background-color: rgba(10, 200, 30, 0.5); border-radius: 10px; float: left; margin: 10px; } .box img { width: 100%; /*height: 200px;*/ border-radius: 50%; } .box p { text-align: center; } </style> </head> <body> <div id="app"> <div class="wrap"> <tag></tag> <tag></tag> <tag></tag> <tag></tag> </div> </div> </body> <script src="js/vue.js"></script> <script> let titleTag = { template: ` <p> <b> 清纯妹 </b> </p> `, }; let tag = { template: ` <div class="box"> <img src="img/111.jpg" alt=""> <title-tag /> <p @click="fn"> 锤它:<b>{{ num }}下</b> </p> </div> `, // 能被复用的组件(除了根组件),数据都要做局部化处理,因为复用组件后,组件的数据是相互独立的 // data的值为绑定的方法的返回值,返回值是存放数据的字典 data () { return { num: 0 } }, methods: { fn() { this.num ++ } }, components: { titleTag, } }; new Vue({ el: '#app', components: { tag, } }); ` class P: num = 0 def __init__(n): this.n = n p1 = P() p2 = P() P.num = 10 p1.num p2.num ` </script> </html>
组件传参--父传子
数据交互--父传子--通过绑定属性的方式 1.父组件提供数据 2.在父组件模板中,为子组件标签设置自定义属性,且自定义属性绑定的值由父组件提供 3.在子组件实例中,用过props实例成员获得自定义属性,然后就可以使用父组件的数据
使用父组件的数据,在子组件的模板上进行渲染步骤流程:
1.先创建子组件;
2.在父组件中注册子组件(components)
3.在父组件模板中渲染出子组件,且为子组件标签设置自定义属性,自定义属性值由父组件提供
4.在子组件实例中,通过props实例成员获得自定义属性,便可使用父组件提供的数据
<!DOCTYPE html> <html lang="en"> <head> <meta charset='UTF-8'> <title>父传子</title> <style> .wrap { width: calc(200px * 4 + 80px); margin: 0 auto; user-select: none; } .box { width: 200px; height: 260px; /*border: 1px solid black;*/ background-color: rgba(10, 200, 30, 0.5); border-radius: 10px; float: left; margin: 20px; } .box img { width: 100%; height: 160px; border-radius: 50%; margin: 0 auto; display: block; } .box p { text-align: center; } </style> </head> <body> <div id="app"> <son v-for="photo in photos" v-bind:photo="photo"></son> </div> </body> <script src="js/vue.js"></script> <script> let photos = [ {title: '女友1号', img:'img/111.jpg',}, {title: '女友2号', img:'img/222.jpg',}, {title: '女友3号', img:'img/333.jpg',}, {title: '女友4号', img:'img/444.jpg',}, {title: '女友1号', img:'img/111.jpg',}, {title: '女友2号', img:'img/222.jpg',}, {title: '女友3号', img:'img/333.jpg',}, {title: '女友4号', img:'img/444.jpg',}, ]; let son = { // 在组件内部就可以通过设置的自定义属性,拿到外部选择子组件提供给属性的的值 props:['photo'], template: ` <div class="box"> <img :src="photo.img" alt=""> <p>{{ photo.title }}</p> <p @click="fn">亲亲{{ num }}下</p> </div> `, data(){ return{ num: 0 } }, methods:{ fn(){ this.num ++ } } }; new Vue({ el:'#app', data:{ photos, }, components: { son } }); /** * 1.数据在父组件中产生 * 2.在父组件中渲染组件,子组件绑定自定义属性,附上父组件中的数据 * 3.子组件自定义属性在子组件中的props成员中进行声明(采用字符串发射机制) * 4.在子组件内部,就可以用props声明的属性(直接作为变量)来使用父组件的数据 */ </script> </html>
<style> .info { text-align: center; width: 200px; padding: 3px; box-shadow: 0 3px 5px 0 pink; float: left; margin: 5px; } .info img { width: 200px; } </style> <div id="app"> <!-- 2) 在父组件模板中,为子组件标签设置自定义属性,绑定的值由父组件提供 --> <info v-for="info in infos" :key="info.image" :myinfo="info"></info> </div> <script src="js/vue.js"></script> <script> let infos = [ { image: 'img/001.png', title: '小猫' }, { image: 'img/002.png', title: '蛋糕' }, { image: 'img/003.png', title: '蓝糕' }, { image: 'img/004.png', title: '恶犬' }, ]; //局部组件 let info = { template: ` <div class="info"> <img :src="myinfo.image" alt=""> <p><b>{{ myinfo.title }}</b></p> </div> `, // 3) 在子组件实例中,通过props实例成员获得自定义属性 props: ['myinfo'] }; //父组件 new Vue({ el: '#app', components: { info, }, data: { infos, // 1) 父组件提供数据 } }) </script>
组件交互--子传父(由子组件传递数据)
组件交互--子传父 1.数据由子组件提供 2.子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来 3.父组件为子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数
<!DOCTYPE html> <html lang="en"> <head> <meta charset='UTF-8'> <title>作业</title> <style> .box { width: 200px; height: 260px; /*border: 1px solid black;*/ background-color: rgba(10, 200, 30, 0.5); border-radius: 10px; float: left; margin: 20px; } .box img { width: 100%; height: 160px; border-radius: 50%; margin: 0 auto; display: block; } </style> </head> <body> <div id="app"> <p><button @click="fn('tv')">电视</button></p> <p><button @click="fn('phone')">手机</button></p> <!--<div v-for="da in das">--> <!--<img :src="da.img"/>--> <!--<p>{{ da.title }}</p>--> <!--</div>--> <tag v-for="tv in das" :tv="tv" @change="changeFn"></tag> <h2 style="color: red;">{{ index }}</h2> </div> </body> <script src="js/vue.js"></script> <script> let ad_data = { tv: [ {title: 'tv1', img:'img/111.jpg',}, {title: 'tv2', img:'img/222.jpg',}, {title: 'tv3', img:'img/333.jpg',}, {title: 'tv4', img:'img/444.jpg',}, ], phone:[ {title: 'phone1', img:'img/111.jpg',}, {title: 'phone2', img:'img/222.jpg',}, {title: 'phone3', img:'img/333.jpg',}, {title: 'phone4', img:'img/444.jpg',}, ] }; let tag = { props: ['tv'], template: ` // 1.点击触发子组件该事件 <div class="box" @click="choiceFn"> <img :src="tv.img" alt=""> <p>{{ tv.title }}</p> </div> `, methods:{ choiceFn(){ // 2.自行触发,提供数据,将数据用事件形式传给父组件 // 注意:$emit()中第一个参数是自定义的属性名,不是函数名) this.$emit('change',this.tv) } } }; new Vue({ el:'#app', data:{ das: ad_data['tv'], index: '未选任何广告' }, methods:{ fn(ad){ this.das = ad_data[ad] }, // 3.接收子组件提供的数据,触发子组件提供的事件 changeFn(dat){ console.log(dat); this.index = dat.title } }, components:{ tag } }) // console.log(data) </script> </html>
<style> .close:hover { cursor: pointer; color: red; } </style> <div id="app"> <p> <input type="text" v-model="userMsg"> <button @click="sendMsg">留言</button> </p> <ul> <!-- 2) 子组件内部通过触发系统事件,发送一个自定义事件,将数据携带出来 --> <msg-li @remove_msg="removeAction" v-for="(msg, i) in msgs" :msg="msg" :index="i" :key="msg"></msg-li> </ul> </div> <script src="js/vue.js"></script> <script> let msgLi = { template: ` <li> <span class="close" @click="deleteMsg(index)">x </span> <span>第{{ index + 1 }}条:</span> <span>{{ msg }}</span> </li> `, props: ['msg', 'index'], methods: { // 最先触发系统的click事件 deleteMsg(i) { // 1) 数据由子组件提供 // $emit('自定义事件名', 参数们) this.$emit('remove_msg', i); } } }; new Vue({ el: '#app', data: { msgs: [], userMsg: '' }, methods: { sendMsg() { if (this.userMsg) { this.msgs.push(this.userMsg); this.userMsg = ""; } }, // 3) 父组件位子组件标签的自定义属性通过方法实现,就可以通过参数拿到子组件传递处理的参数 removeAction(i) { this.msgs.splice(i, 1) } }, components: { msgLi } }) </script>