Vue的传值

目录

1. 属性传值

1.1 语法

1.2 属性和数据源同名

2. 反向传值

2.1 属性绑定+自定义事件

简单案例:

购物车算总价案例:

2.2 v-model 组件的双向数据绑定

3. 透传(多层组件传值)

3.1 类型透传

3.2 属性穿透 v-bind="$attrs"

 3.3 方法穿透 v-on="$listeners"

 4. 获取组件

5. 依赖provide注入indect


1. 属性传值

1.1 语法

父组件中,其中msg是父组件的数据

// 静态传值 直接将静态数据hello传过去

// 动态传值 msg为app父组件的数据源


子组件中,当数据源中没有同名的数据时,可以通过this来访问这个属性


box1组件-----{{ title }}

//script标签中——注册 props:["title"], methods: { fn() { console.log(this.title); } },

结果:

Vue的传值_第1张图片

1.2 属性和数据源同名

当属性和数据源中的data的数据同名时:vue2.x劫持的顺序不同 所有有优先级;vue3.x data中的同名数据不做代理(不生效)

子组件的模板中显示的是属性传值过来的内容,访问时,得到的是子组件本身数据源中的数据,并且会报警告。

Vue的传值_第2张图片

子组件不能通过this直接修改这个同名变量(vue2.x可以直接修改同名变量的值,且子组件模板会刷新,但父组件数据不变;vue3.x不可以,会报错,title为只读)

原因: 单向数据流:数据只能由父级组件流向子组件(父级组件的数据源更新,会重新刷新模板,重新传新的属性,两个模板都会刷新)。反过来,数据不能由子级组件流向父级组件(会造成死循环),否则程序混乱且难以管理

注:vue2.0 一个template标签只能有一个根元素(简单说就是只能有一个div标签,其余的都在这个div中写);vue3.0解决了这个问题,但还是使用2.0的习惯吧

补充知识:函数声明在a作用域,在b作用域调用,那它就在声明作用域中运行

2. 反向传值

像上面可以知道,子组件不能修改父组件传过来的值,但在实际开发中还是需要通过子组件来修改父组件中的数据,那这个时候就需要通过反向传值,将子组件的值传给父组件。

2.1 属性绑定+自定义事件

子级组件想要修改父级组件的数据,需要绑定事件,将子级组件修改的数据通过事件的实参传给父级组件,然后再把父级组件的数据改为子级组件传过来的数据,从而刷新页面。

语法:

父组件:监听事件

Box子组件内部:触发事件 this.$emit("myevent","传参数")

简单案例:

//父组件

//方法,监听自定义事件myevent
methods: {
    box1_change_msg(arg) {
      this.msg = arg;
    }
  }

//box1子组件

box1组件-----{{ title }}

//方法:自定义事件myevent 触发事件 将要修改的数据传过去 methods: { change_app_data() { this.$emit("myevent","box1向app反向传过去的数据") } }

Vue的传值_第3张图片

Vue的传值_第4张图片

购物车算总价案例:

        前面文章中有用html实现购物车的功能,现在将这个功能用Vue框架来实现,体现了反向传值(子组件的按钮点击了,不能直接修改父组件中的count,需要利用属性绑定和自定义事件来实现数据的反向传值)

父组件(App):


子组件(Goodsbox):


2.2 v-model 组件的双向数据绑定

语法:

父组件:

vue2.0  v-model是语法糖:  :value="msg"  @input="(arg)=>{this.msg=arg}"

vue3.0  v-model:value是语法糖 :value="msg" @update:value=(arg)=>{ msg = arg}

子组件:注册属性,方法中使用this.$emit("update:"属性名","要传的数据")

简单案例:

// 父组件

//父组件数据源
data() {
    return {
      msg: "app组件中的数据",
      key: "app中的key数据",
    }
 }

//子组件Box2

box2组件-----{{ value }}----{{ keywords }}

//注册属性 props: ["value","keywords"], //方法 传值 methods: { v_model_passValue() { this.$emit("update:value", "box2传给app的value数据"); this.$emit("update:keywords","box2传给app的keywords数据") } }

Vue的传值_第5张图片

Vue的传值_第6张图片

3. 透传(多层组件传值)

3.1 类型透传

语法:

父组件中设置了类名,子组件渲染时会自动加上父组件设置的类名;子组件也有类名时,会合并两个类名。

父级组件绑定属性 子组件中给孙组件绑定穿透属性:v-bind="$attrs" 事件透传 同理:v-on="$listeners"

3.2 属性穿透 v-bind="$attrs"

Box3将属性传给下一级组件(Box4)时,自己Box3是不能注册该属性的,才能传给下一子级。

//父组件 app中 通过属性传值


//子组件 box3

box3组件----{{ count }}

//要传给自己,就不注册;不传,就注册来自己用 // props:["count"], //孙组件 box4

box4组件----{{ count }}

//注册的属性名应该为父组件的属性名 props:["count"],

Vue的传值_第7张图片

如果即要自己用,又想传给自己的子组件时,使用$attrs属性透传。$attrs中保存了父组件传给一级子组件的所有属性值,后代组件可以通过this.$attrs来访问。一级子组件Box3不注册,要透传属性给谁,就在这个标签上面添加v-bind:$attrs,但不能注册。使用时:this.$attrs.属性名

//父组件 app中 通过属性传值


//子组件 box3

box3组件----{{ this.$attrs.count }}

//孙组件 box4

box4组件----{{ this.$attrs.count }}

// 属性透传给box5 // 曾孙组件 box5

box5组件----{{ count }}

//注册的属性名应该为父组件的属性名 props:["count"],

Vue的传值_第8张图片

 

3.3 事件穿透 v-on="$listeners"

vue2.x版本中:父组件app绑定的事件,想要通过孙组件Box4来触发该事件时,需要给子组件Box3添加v-on="$listeners",将事件穿透过去,然后在Box4中来触发该事件。

vue3.x版本中,直接通过v-bind="$attrs"就可以实现事件的穿透,$listenners弃用。

 4. 获取组件

$parent/$root/$options——方便,但尽量不要用,会引起不必要的麻烦,不好解决

$refs(获取组件中节点或者组件)

    

box4组件----{{ count }}

box4中的p1标签

methods: { box4_btn() { // 上级元素 console.log(this.$parent); // 根级元素 console.log(this.$root); // 子级元素 console.log(this.$options.components); // 获取组件中节点或者组件 console.log(this.$refs.p1); } }

Vue的传值_第9张图片

5. 依赖provide注入indect

父级组件提供数据,组件链上的子级组件注入并使用。

简单案例:

// 父组件 app
  provide: {
    msgGlobal: 'provided by app',
    numGlobal: 999
  }

// 子组件们 box2 box3均相同
// 使用

global---{{ msgGlobal }}

numGlobal----{{ numGlobal }}

// 注入 inject: ["msgGlobal", "numGlobal"],

Vue的传值_第10张图片

 虽然看起来很好用,但官方还是不建议使用,因为害怕使用者管理不好,容易出错。

总结:

1. 属性传值     Box内部设计的时候,可以props:["属性名"] 或 props:{属性名:验证函数}

        父组件的数据源更新了就会让子组件接收新的属性值

        父组件给子组件传的数据,可以通过子组件再传给它自己的子组件

2. 反向传值(子组件给父组件传值)重点

因为父组件属性传值给子组件后,子组件不能直接修改属性值(框架设计时单项数据流:数据只能由父级组件流给子级组件)。父组件监听事件(绑定函数),子组件触发事件(调用函数传数据)

语法:

        Box内部:this.$emit("myevent","传参数")

        组件的双向数据绑定:

                                             Box内部:this.$emit("update:title","参数")

3 .透传(多层组件传值)

4. 获取组件 $parent $root $options.components

5. 提供provide注入inject

父级组件提供数据,子级组件注入并使用

6. 中央事件总线、仓库——兄弟组件间的传值

你可能感兴趣的:(vue.js,javascript,前端)