【Vue】Vue中传值的几种方法,案例代码解析

目录

一.反向传值(子组件传值给父组件)

二.$refs

三.$parent

四.$children

五.$attrs/$listeners -----多层传值

六.$root ----根组件

七.依赖注入 provide/inject

八.v-model

九.中央事件总线


一.反向传值(子组件传值给父组件)

        我们经常在网页中遇到如图所示的模态窗,我们想要达到的效果是,点击右上方的关闭按钮,模态窗消失,在vue中我们想让一个元素从页面中隐藏起来,可以采用v-if或者v-show,将值从true(显示)改为false(隐藏)。

        那么我们的思路就是点击关闭按钮,flag的值,代码解释如下

         对关闭按钮绑定点击事件,@click=“clear”   这里的事件绑定在子组件上面,而我们想要达到的效果是改变父组件中的数据(数据驱动页面,页面中模态窗口的显示和隐藏由数据flag决定),

首先我们采用属性传值将flag:true传给子组件

 

 要注意,这里涉及到知识点单项数据流,数据只能由父级组件流向子级主键,修改属性值,只会让子组件刷新,父组件的数据没有更新。解释一下父组件数据传给子组件(属性传值),子组件传给父组件(反向传值)

我们想要解决这个问题,想要改变父组件中的值方法如下(反向传值):

因为数据流是单向的:子组件触发事件 this.$emit("事件名",数据1,数据2,````),父组件绑定事件 @事件名="监听器"

1.在父组件上绑定事件,此事件非官方由自己设计作用是啥

2.子组件中触发自定义事件  this.$emit("第一个参数为触发事件的名字","第二个参数为传给父组件的数据")

3.将子组件传给父组件的值,对父组件中的数据进行更改(反向传值)

代码解析如下:

父组件代码:

子组件代码:

 代码也发出来,大家可以去实现一下哟:

父组件:

<template>
  <div>
    <img class="img" src="https://img0.baidu.com/it/u=3443901670,2726678779&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281"
      alt="">
    <span>父组件中flag的值---{{ flag }}</span>
    <Motail v-if="flag" :a1="flag" @updata="fn"></Motail>
  </div>

</template>

<script>
import Motail from "@/motai/Motail.vue"
export default {
  components: {
    Motail,
  },

  data() {
    return {
      flag: true
    }
  },

  methods: {
    fn(arg) {
      // 事件传进来的参数值为事件触发子组件传给父组件的值
      console.log(arg, "1111111111111");
      this.flag = arg;
    }
  }
}
</script>

<style>
.img {
  width: 100%;
  height: 100%;
}
</style>

 子组件:

<template>
    <div class="Motail">
        <div class="box">
            <div>
                <span>这是弹出的模态窗</span><br>
                <span>打印父组件传过来的a1值---{{ a1 }}</span>
            </div>
            <div class="x" @click="clear1">&times;</div>
        </div>
    </div>
</template>

<script>
export default {
    props:["a1"],
    methods:{
        clear1(){
            // 给关闭按钮绑定点击事件
            // 想办法把父组件中的数据源修改了 
            // 数据驱动页面,页面中模态窗口的显示和隐藏由数据决定的(flag:true)
            console.log(this.a1);//打印父组件的传过来的flag的值
            //this.a1="false";
            // 触发自定义事件  
            // 第一个参数update为触发事件的名字
            // 第二个参数为传给事件的数据(子组件传给父组件)
            this.$emit("updata",false)

            
        }
    }
}
</script>


<style>
.Motail {
    width: 100vw;
    height: 100vh;
    background-color: rgba(112, 112, 112, 0.5);
    position: fixed;
    z-index: 20;
    top: 0px;
    right: 0px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.box {
    width: 300px;
    height: 200px;
    font-weight: 30px;
    font-weight: 800;
    background-color: white;
    position: relative;
    border-radius: 10px;
    line-height: 100px;
    text-align: center;

}

.x {
    height: 30px;
    width: 30px;
    background-color: rgb(116, 119, 121);
    border-radius: 50%;
    color: white;
    font-weight: 800;
    font-size: 30px;
    text-align: center;
    line-height: 30px;
    position: absolute;
    top: 0px;
    right: 0px;

}
</style>

二.$refs

在vue中,并不建议我们去做DOM操作,但是却提供了DOM操作的方法

vue提供的DOM操作的接口,元素或者组件上绑定ref="标记",组件中this.$refs.标记获取

 ​​

 如果我们要获取某个具体的元素,直接对象获取值方法 , 例如:this.$refs.p1获取ref=“p1”的该标签。

 ref 除了获取页面上的元素之外还可以获取组件

例如如下:

 

 这里VueComponent表示该引用数据的构造函数,为vue框架中的类,组件对象由VueCompoent创建。

三.$parent

概括:当前组件的父组件,父组件还可以链式调用获取父组件,根组件没有父组件

在本章博客中一讲到,子组件给父组件传数据,修改父组件的数据较为麻烦,这里介绍一下$parent,可直接修改父组件的数据,省去了绑定事件,触发事件等步骤。

this.$parent中this表示当前组件,.$parent表示当前组件的父组件,可直接this.$parent.flag进行更改父组件中data中的flag值

 扩展:App的父组件为Vue   也就是说根组件为Vue,根组件的构造函数不是VueCompoent,而是Vue。根组件的父组件为undefined

四.$children

概括:是一个数组,数组中是当前组件的子组件们,不包括子元素,不保证顺序

同三,可以用$children访问子组件,一个子组件有且仅有一个父组件,一个父组件可以有很多子组件。简单点说就是一个儿子只能有一个爸爸,而一个爸爸可以有很多个儿子。

既然我们说到一个父组件的子组件不止一个,则返回的就不是一个对象而是一个数组

 $children也有很多弊端,比如我们在this.$children[0] 取到第一个子组件,如果我们将第一个子组件v-if="false"改为哦v-for="true",该组件不一定是第一个(按照时间添加到当前组件的最后,与添加的时间有关),这里取到的顺序与我们书写代码的顺序无关。所以我们不建议用$children来获取子组件

五.$attrs/$listeners -----多层传值

在几重父子关系中传值用反向传值的方法十分繁琐,为了解决这个问题有了多层传值(过渡作用)

attrs 为英语单词属性sttributes的缩写,表示该组件的父组件传的所有属性在该组件下都不会使用,直接传给下一级组件用(图片中表示传给Box2组件),传给Box2过后,再用props:[""]接收。

如果想要修改父组件中的数据,用一中触发事件实现(也就是this.$emit("事件名",数据1,数据2,````)),这里呢也需要添加v-on="$listeners"来起传递作用,监听器的传递。

例子:

App------>Box1-------->Box2

App代码:

<template>
  <div>
    <p>app-----{{ msg }}</p>
    <Box1  :a1="msg" @change="fn"></Box1>
  </div>

</template>

<script>
import Box1 from "@/Box/Box1.vue"
export default {
  data(){
    return {
      msg:"app组件的数据"
    }
  },
  methods:{
    fn(arg){
      console.log(arg,1111111111);//arg表示box2传回来的数据
      this.msg=arg;
    }
  },
  components:{
    Box1,
  }
}

</script>

<style>
</style>

 App的子组件Box1的代码:

<template>
    <div>
       <Box2 v-bind="$attrs" v-on="$listeners"></Box2>
    </div>
</template>

<script>
import Box2 from "@/Box/Box2.vue"
export default {
  data(){
    return {
      msg:"app组件的数据"
    }
  },
  components:{
    Box2,
  }
}

</script>

<style>
</style>

 App的子组件Box1的子组件Box2代码:

<template>
    <div>
        <p>box2----{{ a1 }}</p>
        <button @click="fn1">box2-btn</button>
    </div>
</template>
<script>
export default {
    props: ["a1"],
    methods:{
        fn1(){
            console.log(this.a1);
            this.$emit("change","这是box2传给App的数据")
        }
    }
}
</script>
<style>

</style>

六.$root ----根组件

        this.$root可以获取到根组件,每个vue框架中有且只有一个根组件  ,我们可以将数据放到根组件中,避免的子父组件之间传值的繁琐。

在之后的使用中我们可以用$rooot 来对兄弟组件进行传值

七.依赖注入 provide/inject

依赖注入比多层传值更加简洁,多层传值中间组件需要写代码v-bind="$attrs" v-on="$listeners"进行过渡。依赖注入弊端不能修改提供者提供的数据。所有组件都可以成为provide的提供者,inject为提供者的后代

provide提供数据 

<script>
export default {
  provide(){
    return{
      msg2:"app组件提供的数据"
    }
  }
}

</script>

inject接收数据

<script>
    export default{
        inject:["msg2"]
    }
</script>

八.v-model

在之前的学习阶段,我们知道v-model是语法糖,同样的这里也可以使用

在一中,我们将 :a1改为 :value,   将   @updata改为@input,

可以改写成以下格式 

<Box v-model="flag"></Box>

v-model可以省去下面这一步,也就是得到事件触发传过来的值对当前组件的值进行更改。

v-model="flag"的底层就是2个语法的合成

1.属性绑定 :value="flag"

2.绑定了@input还是函数中把接收的数据设置给了this.flag

 v-model是下述的一个特例(省去了事件绑定步骤)

九.中央事件总线

在$root中提到可以在根组件vue上进行操作,但是在渲染网页的vue上去各种各样的绑定会对性能造成影响。

解决方案:新建vue,在新建的vue上进行各种绑定。通过创建一个新的vm对象,专门统一注册事件,供所有组件共同操作,达到所有组件随意隔代传值的效果

使用例子:

this.$bus.emit

 this.$bus.on

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值