Vue父子組件數據雙向綁定(父傳子、子傳父)及ref、$refs、is、:is的使用與區別
既然有父傳子那麼肯定有子傳父,有子傳父肯定也有兩者之間相互綁定
這裡我們先看一下子傳父的寫法:
一、子傳父:$emit()
看代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>子傳父</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <style type="text/css"> button { margin-left: 5px; } </style> <body> <div id="app"> <cpn1 @itemclick="cpnclick"></cpn1> </div> <template id="cpn1"> <div> <button type="button" v-for="item in menu" :key="item.id" @click="btnclick(item)">{{item.name}}</button> </div> </template> <script type="text/javascript"> const cpn = { template: "#cpn1", data() { return { menu: [{ id: 'one', name: '首頁' }, { id: 'two', name: '分類' }, { id: 'three', name: '購物' }, { id: 'four', name: '我的' }, ], } }, methods: { btnclick(item) { this.$emit('itemclick', item) // 子傳父 在子組件中做一個點擊事件通過$emit派發出 給父組件 同時可以攜帶參數 } } }; const vm = new Vue({ el: '#app', methods: { cpnclick(item) { console.log('cpnclick' + item.name); } }, components: { "cpn1": cpn } }) </script> </body> </html>
打印效果:
兩者之間的關系:
1、父組件可以使用 props 把數據傳給子組件。
2、子組件可以使用 $emit 觸發父組件的自定義事件。
二、監聽原生點擊事件:.native
不加.native時,不會觸發原生的點擊事件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>不加native修飾符</title> </head> <style> div{ cursor: pointer; } </style> <body> <div id="app"> <cpn @click="handelClick"></cpn> // 這裡沒有加native修飾符 </div> <!-- 子組件 --> <template id="cpn"> <div> 我是子組件 </div> </template> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script> const cpn = { template:'#cpn', } const app = new Vue({ el: "#app", methods: { handelClick(){ console.log('click'); } }, components:{ cpn } }) </script> </body> </html>
效果如下:
不加修飾符是不會監聽到原生點擊事件的。
如果是加瞭.native修飾符時:
添加方法:
<cpn @click.native="handelClick"></cpn>
效果如下圖所示:
三、組件通信的案例:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <cpn :number1="num1" :number2="num2"></cpn> </div> <template id="cpn"> <div> <h2>{{datanum1}}</h2> <input type="text" v-model="datanum1"/> <h2>{{datanum2}}</h2> <input type="text" v-model="datanum2"/> </div> </template> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script> const cpn = { template:'#cpn', data(){ return { datanum1:this.number1, datanum2:this.number2, } }, props:{ number1:{ type:[String,Number] }, number2:{ type:[String,Number] }, } } const app = new Vue({ el: "#app", data() { return { num1:1, num2:2 } }, components:{ cpn } }) </script> </body> </html>
效果如下:
四、實現父子之間的值的雙向綁定
在子組件中添加監聽器,利用props和$emit來進行父子之間的雙向綁定
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <cpn :number1="num1" :number2="num2" @dataclick1="changeClick1" @dataclick2="changeClick2"></cpn> </div> <template id="cpn"> <div> <h2>{{datanum1}}</h2> <h3>number1:{{number1}}</h3> <input type="text" v-model="datanum1" /> <h2>{{datanum2}}</h2> <h3>number2:{{number2}}</h3> <input type="text" v-model="datanum2" /> </div> </template> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script> const cpn = { template: '#cpn', data() { return { datanum1: this.number1, datanum2: this.number2 } }, props: { number1: { type: [String, Number] }, number2: { type: [String, Number] } }, watch: { datanum1(n) { console.log('datanum1被監聽瞭'); this.$emit('dataclick1', n / 100) }, datanum2(n) { console.log('datanum2被監聽瞭'); this.$emit('dataclick2', n * 100) } } } const app = new Vue({ el: "#app", data() { return { num1: 1, num2: 2 } }, methods: { changeClick1(value) { this.num1 = value }, changeClick2(value) { this.num2 = value } }, computed: { }, components:{ cpn } }) </script> </body> </html>
效果
一個是除10一個是
五、父訪問子 $refs
JavaScript中獲取元素可以使用document.querySelector,那可以在Vue中使用嗎?
我們可以測試一下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <p id="bb" @click="handelClick" ref="aa">Nanchen</p> </div> <script type="text/javascript"> const vm = new Vue({ el: '#app', data() { return { } }, methods: { handelClick(){ var bb = document.querySelector('bb'); console.log(bb); } } }) </script> </body> </html>
打印結果:
答案是可以的,但是如果使用原生JS獲取元素的話,那麼用Vue就沒有意義瞭,Vue中有特定的語法
官網解釋:
$refs方式:ref 被用來給元素或子組件註冊引用信息。引用信息將會註冊在父組件的 $refs 對象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實例
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <p id="bb" @click="handelClick" ref="aa">Nanchen</p> </div> <script type="text/javascript"> const vm = new Vue({ el: '#app', data() { return { } }, methods: { /* handelClick(){ var bb = document.querySelector('bb'); console.log(bb); } */ handelClick() { console.log(this.$refs.aa); } } }) </script> </body> </html>
效果與上圖一致:
六、使用$refs獲取組件中的值
既然可以獲取普通元素那麼也可以獲得組件中的元素或者值
看這個例子:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <cpn ref="aaa"></cpn> <button @click="handelClick">點擊</button> </div> <!-- 子組件 --> <template id="cpn"> <div> 我是子組件 </div> </template> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script> const cpn = { template:'#cpn', data(){ return { name:'我是子組件的name' //獲取子組件的屬性 } }, } const app = new Vue({ el: "#app", methods: { handelClick(){ console.log(this.$refs.aaa.name); } }, components:{ cpn } }) </script> </body> </html>
效果如下:
下面看一個擴展:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <count ref="one" @change="handclick"></count> <count ref="two" @change="handclick"></count> <h2>{{total}}</h2> </div> <script type="text/javascript"> Vue.component('count',{ template: `<div @click="handclick"> {{number}} </div>`, data(){ return{ number:0 } }, methods:{ handclick(){ this.number++; this.$emit('change') } } }) const vm = new Vue({ el:'#app', data(){ return{ total:0 } }, methods:{ handclick(){ this.total= this.$refs.one.number + this.$refs.two.number } } }) </script> </body> </html>
效果如下:
不僅如此,ref還可以調用組件中的方法:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <hello-world ref="hello"></hello-world> <button @click="getHello">獲取helloworld組件中的值</button> </div> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script> Vue.component('helloWorld',{ template:`<div>helloWorld</div>`, data(){ return { number:0 } }, methods:{ /*handelClick(){ console.log('我是子組件的方法'); }*/ } }) const app = new Vue({ el: "#app", data: { }, methods: { getHello(){ /* this.$refs.hello.handelClick(); */ console.log(this.$refs.hello.$el.innerHTML); } }, }) </script> </body> </html>
效果如下:
六、is與:is
is
作用:解決瞭html模板的限制。
看下面這段代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <table> <row></row> </table> </div> <script type="text/javascript"> Vue.component('row',{ template: '<tr><td>111</td></tr>' }) const vm = new Vue({ el:'#app', data(){ return{ } }, }) </script> </body> </html>
會正常輸出
但是:
會發現tr並不在table中,
解決辦法:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div id="app"> <table> <tr is="row"></tr> </table> </div> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script> Vue.component('row', { template: '<tr><td>111</td></tr>' }) const app = new Vue({ el: "#app", }) </script> </body> </html>
打印結果:
用:is還可以用來綁定動態組件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <component :is="type"></component> <button type="button" @click="changeClick">切換</button> </div> <script type="text/javascript"> // 這裡要定義兩個全局組件 Vue.component('child-one',{ template:'<div>child-one</div>' }), Vue.component('child-two',{ template:'<div>child-two</div>' }) const vm = new Vue({ el:'#app', data(){ return{ type:'child-one' } }, methods:{ changeClick(){ this.type = this.type === 'child-one' ? 'child-two' :'child-one' } } }) </script> </body> </html>
效果如下:
以上就是Vue父子組件數據雙向綁定(父傳子、子傳父)及ref、$refs、is、:is的使用與區別的詳細內容,更多關於Vue父子組件數據雙向綁定的資料請關註WalkonNet其它相關文章!