既然有父传子那么肯定有子传父,有子传父肯定也有两者之间相互绑定
这里我们先看一下子传父的写法:
一、子传父:$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/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>
效果如下:
不加修饰符是不会监听到原生点击事件的。
如果是加了.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/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>
效果如下:
四、实现父子之间的值的双向绑定
在子组件中添加监听器,利用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/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被监听了');
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一个是
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() {
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/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>
效果如下:
下面看一个扩展:
<!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/vue@2.6.10/dist/vue.js"></script>
<script>
Vue.component('helloWorld',{
template:`<div>helloWorld</div>`,
data(){
return {
number:0
}
},
methods:{
}
})
const app = new Vue({
el: "#app",
data: {
},
methods: {
getHello(){
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/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>
打印结果:
用: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父子组件数据双向绑定的资料请关注编程网其它相关文章!