Vue父子組件數(shù)據(jù)雙向綁定(父傳子、子傳父)及ref、$refs、is、:is的使用與區(qū)別
既然有父傳子那么肯定有子傳父,有子傳父肯定也有兩者之間相互綁定
這里我們先看一下子傳父的寫法:
一、子傳父:$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)
// 子傳父 在子組件中做一個(gè)點(diǎn)擊事件通過$emit派發(fā)出 給父組件 同時(shí)可以攜帶參數(shù)
}
}
};
const vm = new Vue({
el: '#app',
methods: {
cpnclick(item) {
console.log('cpnclick' + item.name);
}
},
components: {
"cpn1": cpn
}
})
</script>
</body>
</html>打印效果:

兩者之間的關(guān)系:
1、父組件可以使用 props 把數(shù)據(jù)傳給子組件。
2、子組件可以使用 $emit 觸發(fā)父組件的自定義事件。
二、監(jiān)聽原生點(diǎn)擊事件:.native
不加.native時(shí),不會(huì)觸發(fā)原生的點(diǎn)擊事件
<!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/vue@2.6.10/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>效果如下:

不加修飾符是不會(huì)監(jiān)聽到原生點(diǎn)擊事件的。
如果是加了.native修飾符時(shí):
添加方法:
<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/vue@2.6.10/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>效果如下:

四、實(shí)現(xiàn)父子之間的值的雙向綁定
在子組件中添加監(jiān)聽器,利用props和$emit來進(jìn)行父子之間的雙向綁定
<!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/vue@2.6.10/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被監(jiān)聽了');
this.$emit('dataclick1', n / 100)
},
datanum2(n) {
console.log('datanum2被監(jiān)聽了');
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>效果

一個(gè)是除10一個(gè)是
五、父訪問子 $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>打印結(jié)果:

答案是可以的,但是如果使用原生JS獲取元素的話,那么用Vue就沒有意義了,Vue中有特定的語法
官網(wǎng)解釋:
$refs方式:ref 被用來給元素或子組件注冊(cè)引用信息。引用信息將會(huì)注冊(cè)在父組件的 $refs 對(duì)象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子組件上,引用就指向組件實(shí)例
<!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獲取組件中的值
既然可以獲取普通元素那么也可以獲得組件中的元素或者值
看這個(gè)例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<cpn ref="aaa"></cpn>
<button @click="handelClick">點(diǎn)擊</button>
</div>
<!-- 子組件 -->
<template id="cpn">
<div>
我是子組件
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/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>效果如下:

下面看一個(gè)擴(kuò)展:
<!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還可以調(diào)用組件中的方法:
<!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/vue@2.6.10/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>會(huì)正常輸出
但是:

會(huì)發(fā)現(xiàn)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/vue@2.6.10/dist/vue.js"></script>
<script>
Vue.component('row', {
template: '<tr><td>111</td></tr>'
})
const app = new Vue({
el: "#app",
})
</script>
</body>
</html>打印結(jié)果:

用:is還可以用來綁定動(dòng)態(tài)組件
<!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">
// 這里要定義兩個(gè)全局組件
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父子組件數(shù)據(jù)雙向綁定(父傳子、子傳父)及ref、$refs、is、:is的使用與區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于Vue父子組件數(shù)據(jù)雙向綁定的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- vue子組件改變父組件傳遞的prop值通過sync實(shí)現(xiàn)數(shù)據(jù)雙向綁定(DEMO)
- Vue.js實(shí)現(xiàn)數(shù)據(jù)雙向綁定的代碼示例
- 使用Vue.js實(shí)現(xiàn)數(shù)據(jù)的雙向綁定
- 淺析Vue3中通過v-model實(shí)現(xiàn)父子組件的雙向數(shù)據(jù)綁定及利用computed簡化父子組件雙向綁定
- vue中如何解除數(shù)據(jù)之間的雙向綁定
- vue3中reactive數(shù)據(jù)被重新賦值后無法雙向綁定的解決
- proxy實(shí)現(xiàn)vue3數(shù)據(jù)雙向綁定原理
- vue自定義組件實(shí)現(xiàn)v-model雙向綁定數(shù)據(jù)的實(shí)例代碼
- vue 數(shù)據(jù)雙向綁定的實(shí)現(xiàn)方法
- Vue項(xiàng)目開發(fā)實(shí)現(xiàn)父組件與子組件數(shù)據(jù)間的雙向綁定原理及適用場景
相關(guān)文章
在Vue3中使用BabylonJs開發(fā)?3D的初體驗(yàn)
這篇文章主要介紹了在?Vue3?中使用?BabylonJs?開發(fā)?3D?是什么體驗(yàn),在本文中,向您展示了如何創(chuàng)建?Vue?組件、Babylon?類、在畫布上渲染場景以及創(chuàng)建?3D?網(wǎng)格,需要的朋友可以參考下2022-07-07
vue子組件使用自定義事件向父組件傳遞數(shù)據(jù)
這篇文章主要介紹了vue子組件使用自定義事件向父組件傳遞數(shù)據(jù)的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-05-05
vue3在構(gòu)建時(shí)使用魔法糖語法時(shí)defineProps和defineEmits的注意事項(xiàng)小結(jié)
在 Vue 3.2+ 版本中,可以使用 <script setup> 替代傳統(tǒng)的 script標(biāo)簽來編寫組件,它提供了更簡潔的語法來編寫 Composition API 代碼,這篇文章主要介紹了vue3在構(gòu)建時(shí)使用魔法糖語法時(shí)defineProps和defineEmits的注意事項(xiàng)小結(jié),需要的朋友可以參考下2024-04-04
vue?elementui?實(shí)現(xiàn)搜索欄子組件封裝的示例代碼
這篇文章主要介紹了vue?elementui?搜索欄子組件封裝,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
vuejs如何解決瀏覽器切換頁面后setInterval計(jì)時(shí)器停止執(zhí)行的問題
setinterval()是定時(shí)調(diào)用的函數(shù),可按照指定的周期(以毫秒計(jì))來調(diào)用函數(shù)或計(jì)算表達(dá)式,這篇文章主要給大家介紹了關(guān)于vuejs如何解決瀏覽器切換頁面后setInterval計(jì)時(shí)器停止執(zhí)行的問題,需要的朋友可以參考下2024-01-01
Vue3?使用Element?Plus表格單選帶checkbox功能
這篇文章主要介紹了Vue3?使用Element?Plus表格單選帶checkbox,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11
vue-cli開發(fā)環(huán)境實(shí)現(xiàn)跨域請(qǐng)求的方法
本篇文章主要介紹了vue-cli開發(fā)環(huán)境實(shí)現(xiàn)跨域請(qǐng)求的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-04-04
uniapp+vue3實(shí)現(xiàn)上傳圖片組件封裝功能
這篇文章主要介紹了uniapp+vue3實(shí)現(xiàn)上傳圖片組件封裝功能,首先創(chuàng)建一個(gè)?components 文件在里面進(jìn)行組件的創(chuàng)建,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07

