zoukankan      html  css  js  c++  java
  • 二、Vue组件(component):组件的相互引用、通过props实现父子组件互传值

    一、组件各部分说明及互相引用

    1.一个vue组件由三个部分组成
    	Template
    只能存在一个根元素
    	2.Script
    	3.Style
    scoped:样式只在当前组件内生效
    

    1.1 组件的基本引用代码示例

    重点:第1步,app.vue;第2步,father.vue

    0、src/main.js

    // The Vue build version to load with the `import` command
    // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
    import Vue from 'vue'//【重点1】引入vue.js
    import App from './App'
    
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({//【重点】创建vue组件实例
      el: '#app', //[1]:在index.html里id为#app标签里写入组件内容
      components: { App },//[2]:写入的组件
      template: '<App/>' //[3]:写入的模板名(也可看成一个完整组件)
    })
    

    第1步,src/APP.vue引入子组件示例

    <template>
      <div id="app">
         <img src="./assets/logo.png">
        <Father /> <!-- 【2】第2步,调用子组件 -->
      </div>
    </template>
    
    <script>
    import Father from './components/father' //【1】第1步,引入子组件
    
    export default {
      name: 'App',
      components: {
        Father //【3】第3步,把组件写到此处,目的是把它暴露出去
      },
    
      data () {//【data必须是一个函数】此为标准es6写法,也可写成data:function(),这样才能对每个实例可以维护一份被返回对象的独立的拷贝
        return {
          msg: 'hello',
        }
      },
    }
    </script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    

    第2步,src/components/father.vue

    <template>
      <div> <!-- 第一层只能有一个根标签 -->
        父组件
        <Child /> <!-- 【2】第2步,调用子组件 -->
      </div>
    </template>
    
    <script>
     import Child from './child' //【1】第1步,引入子组件
    
      export default{//需要暴露出去的内容都要写在此处,这样才能被其它组件使用用
        name:'Father',//当前组件名
        components:{//【3】第3步,把组件写到此处,目的是把它暴露出去(其对应import xxx)中的xxx
          Child,
        },
        data(){//data必须是一个函数】此为标准es6写法,也可写成data:function(),这样每个实例可以维护一份被返回对象的独立的拷贝
          return{msg:'father'} //此处一定要记得return
        },
    
      }
    </script>
    
    <style scoped> /* [4]知识点4,此处写的样式只对当前father.vue组件生效 */
    </style>
    
    

    第3步,src/components/child.vue

    <template>
      <div>
        子组件
      </div>
    </template>
    
    <script>
      export default{
        name:'child',
        data(){
    return{ tit:'child'}
        }
      }
    </script>
    
    <style scoped>
    </style>
    
    

    效果:
    父组件
    子组件

    二、父-->子组件通信(交互)props----父传子

    1.通过设置子组件的Props(道具)接收父组件的传值代码示例

    father.vue

    1、父组件设置一个属性:(如name=xxx)

    <template>
      <div>
        <h1>主题:父组件向子组件传值</h1>
        <Child title='父组件的数据' /> <!-- 【1】第1步,建一个属性title=xx,写入xx数据 -->
      </div>
    </template>
    
    <script>
     import Child from './child'
    
      export default{
        name:'Father',
        components:{
          Child,
        },
        data(){
          return {msg:'father'}
        },
    
      }
    </script>
    
    <style scoped>
    </style>
    
    

    child.vue

    2、子组件通过设置props接收父组件传过来的内容:props:[ 'name' ]或 props:{name:{type:String,default:''}}
    3、显示父组件传的内容:{{name}}

    <template>
      <div>
        <!-- 【3】显示父组件传过来的值 -->
        <h2>子组件:{{title}}</h2>
      </div>
    </template>
    
    <script>
      export default{
        name:'child',
        data(){
          return{}
        },
        props:["title"] #【2】通过props接收父组件传的数据
      }
    </script>
    
    <style scoped>
    </style>
    

    效果:箭头部分即父组件title=xxx,传过来的值
    在这里插入图片描述

    2.向子组件传data里的动态数据

    father.vue

    1、在data(){title:'title content'}
    2、把<child title=xxx /> 中的xx换成data里的title

    <template>
      <div>
        <h1>主题:父组件向子组件传data里的动态值</h1>
        <Child v-bind:title="msg" /> <!-- 【1】第1步,title=xx,的内容写成data里的属性名 -->
      </div>
    </template>
    
    <script>
     import Child from './child'
    
      export default{
        name:'Father',
        components:{
          Child,
        },
        data(){
          return {
            msg:"父组件data内的动态的数据",//【1】数据里写一个属性:值;
            }
        },
    
      }
    </script>
    
    <style scoped>
    </style>
    
    

    child.vue

    3、child里不变

    <template>
      <div>
        <!-- 【2】显示父组件传过来的值 -->
        <h2>子组件:{{title}}</h2>
      </div>
    </template>
    
    <script>
      export default{
        name:'child',
        data(){
          return{tit:'child'}
        },
        props:["title"]//[1]接收父组件的属性名(在father.vue里的<child title=xx /> )
      }
    </script>
    
    <style scoped>
    </style>
    

    在这里插入图片描述

    3.改变data里的msg,将自动传给子组件示例

    <template>
      <div>
        <h1>主题:父组件向子组件传data里的动态值</h1>
        <Child v-bind:title="msg" /> <!-- 【1】第1步,title=xx,的内容写成data里的属性名 -->
        <button v-on:click="change_msg">改变一下</button>
      </div>
    </template>
    
    <script>
     import Child from './child'
    
      export default{
        name:'Father',
        components:{
          Child,
        },
        data(){
          return {
            msg:"父组件data内的动态的数据",//【1】数据里写一个属性:值;
            }
        },
        methods:{
          change_msg(event){//按键的处理函数
            this.msg='改变一下msg消息'
          }
        }
      }
    </script>
    
    <style scoped>
    </style>
    

    效果:
    在这里插入图片描述

    4.子组件通过props,父组件的v-model,随时获取表单数据示例

    father.vue

    【1】第1步,再定义一个数据,初始数据随便设置
    【2】第2步,再v-bind绑定第2个属性msg(此可随便设置,子组件的props对应即可)为data里的msg2
    【3】第3步,在表单里绑定data里的msg2

    <template>
      <div>
        <h1>主题:父组件通过v-model实时向子组件传data里的值</h1>
        <input v-model="msg2" />         <!-- 【3】第3步,在表单里绑定data里的msg2 -->
        <Child v-bind:title="msg" v-bind:msg='msg2' /> <!-- 【2】第2步,再v-bind绑定第2个属性msg(此可随便设置,子组件的props对应即可)为data里的msg2 -->
        <button v-on:click="change_msg">改变一下</button>
      </div>
    </template>
    
    <script>
     import Child from './child'
    
      export default{
        name:'Father',
        components:{
          Child,
        },
        data(){
          return {
            msg:"父组件data内的动态的数据",//数据里写一个属性:值;
            msg2:'父向子组件传递的第2个数据'//【1】第1步,再定义一个数据,初始数据随便设置
            }
        },
        methods:{
          change_msg(event){
            this.msg='改变一下msg消息'
          }
        }
    
      }
    </script>
    
    <style scoped>
    </style>
    

    child.vue

    【1】接收父组件的属性1、2的名字title,msg(在father.vue里的<child title= msg= />
    【2】显示父组件传过来的属性1,属性2

    <template>
      <div>
        <!-- 【2】显示父组件传过来的属性1,属性2  -->
        <h2>子组件:{{title}}--{{msg}}</h2>
      </div>
    </template>
    
    <script>
      export default{
        name:'child',
        data(){
         return{ tit:'child'}
        },
        props:["title","msg"]//[1]接收父组件的属性1、2的名子(在father.vue里的<child title=xx msg=xxx /> )
      }
    </script>
    
    <style scoped>
    </style>
    

    效果:输入框值变动,子组件随时跟着变动
    在这里插入图片描述

    5.通过子组件的props限制父组件传过来的数据类型

    father.vue

    【1】再定义一个数据
    【2】第2步,对子组件,再加个v-bind绑定第2个属性age(此可随便设置,子组件的props对应即可)为data里的num

    <template>
      <div>
        <h1>主题:父组件通过v-model实时向子组件传data里的值</h1>
        <input v-model="msg2" />
        <Child v-bind:title="msg" v-bind:msg='msg2' :age='num' /> <!-- 【2】第2步,再v-bind绑定第2个属性age(此可随便设置,子组件的props对应即可)为data里的num -->
        <button v-on:click="change_msg">改变一下</button>
      </div>
    </template>
    
    <script>
     import Child from './child'
    
      export default{
        name:'Father',
        components:{
          Child,
        },
        data(){
          return {
            msg:"父组件data内的动态的数据",//数据里写一个属性:值;
            msg2:'父向子组件传递的第2个数据',
            num:'hello'//【1】再定义一个数据
            }
        },
        methods:{
          change_msg(event){
            this.msg='改变一下msg消息'
          }
        }
    
      }
    </script>
    
    <style scoped>
    </style>
    
    

    child.vue

    【1】把props改成字典写法,逐个对其属性的数据类型进行限定,把age的数据类型限定为数字
    【2】显示父组件传过来的属性3:age

    <template>
      <div>
        <!-- 【2】显示父组件传过来的属性1,属性2,属性3:age  -->
        <h2>子组件:{{title}}--{{msg}}----{{age*2}}</h2>
      </div>
    </template>
    
    <script>
      export default{
        name:'child',
        data(){
          return{tit:'child'}
        },
        props:{//【1】把props改成字典写法,逐个对其属性的数据类型进行限定
          title:String,
          msg:String,
          age:Number //此处把age的数据类型限定为数字
        }//["title","msg","age"]//[1]接收父组件的属性1、2的名子(在father.vue里的<child title=xx msg=xxx /> )
      }
    </script>
    
    <style scoped>
    </style>
    
    

    效果:

    • 因为fahter.vue里的data的num数据类型为'hello'是字符串类型
    • 又child.vue里的props限定了num必须为数字
    • 所以控制台会报错:Invalid prop: type check failed for prop "age". Expected Number with value NaN, got String with value "hello".
    • 只有父组件里的数据为数字(如Num=10),此处才能正确运行显示:20(num2=102)在这里插入图片描述

    5.2 子组件用props把父组件传过来的数据[限定为多种数据类型]、[设置为必需选项]

    【1】设置为支持多种数据类型 title:[String,Number],父组件传的title值可以为字符串,或数字
    【2】设置为是否必须选项,如果父组件没有传msg=xx这个属性,就报错

    msg:{//【2】设置为是否必须选项
            type:String,
            required:true
          }
    

    原码:

    <template>
      <div>
        <!-- 显示父组件传过来的属性1,属性2,属性3:age  -->
        <h2>子组件:{{title}}--{{msg}}----{{age*2}}</h2>
      </div>
    </template>
    
    <script>
      export default{
        name:'child',
        data(){
          return {tit:'child'}
        },
        props:{
          title:[String,Number],//【1】设置为支持多种数据类型
          msg:{//【2】设置为是否必须选项
            type:String,
            required:true
          },
          age:Number, 
        }
      }
    </script>
    
    <style scoped>
    </style>
    
    

    效果:父组件没传msg,警告信息
    在这里插入图片描述

    5.3在子组件props设置默认值(如果父不传,则使用默认值)

    child.vue

    <template>
      <div>
        <!-- 【2】显示父组件传过来的属性1,属性2,属性3:age  -->
        <h2>子组件:{{title}}--{{msg}}----{{age*2}}</h2>
      </div>
    </template>
    
    <script>
      export default{
        name:'child',
        data(){
          return {tit:'child'}
        },
        props:{
          title:[String,Number],
          msg:{
            type:String,
            required:true
          },
          age:{//【1】设置默认值
            type:Number,
            default:5
            }
        }
      }
    </script>
    
    <style scoped>
    </style>
    

    结果:父组件没传num,子组件用默认值5计算出来的值5*2=10
    在这里插入图片描述

    6.父组件data数据为字典时,向子组件props传值

    father.vue

    【1】第1步,设置一个字典的数据
    【2】第2步,再v-bind绑定ojbData为data里的fatherObj

    <template>
      <div>
        <h1>主题:父组件通过v-model实时向子组件传data里的【对象类型数据】值</h1>
        <input v-model="msg2" />
        <Child v-bind:title="msg" :msg="msg2" :objData="fatherObj"  /> <!-- 【2】第2步,再v-bind绑定ojbData为data里的fatherObj -->
        <button v-on:click="change_msg">改变一下</button>
      </div>
    </template>
    
    <script>
     import Child from './child'
    
      export default{
        name:'Father',
        components:{
          Child,
        },
        data(){
          return {
            msg:"父组件data内的动态的数据",
            msg2:'父向子组件传递的第2个数据',
            num:10,
            fatherObj:{//【1】第1步,设置一个字典的数据
              name:'flying',
              age:22
            }
            }
        },
        methods:{
          change_msg(event){
            this.msg='改变一下msg消息'
          }
        }
    
      }
    </script>
    
    <style scoped>
    </style>
    

    child.vue

    【1】父组件传值是字典时,props的特殊写法

    • 【1.1】此处数据类型必须设置为Object
    • 【1.2】这里返回值"未知"、0等可随意,目的是如果父组件没有传对应的值,就用此默认的值

    【2】显示父组件传过来的字典类型数据

    <template>
      <div>
    
        <h2>子组件:{{title}}--{{msg}}----{{age*2}}</h2>
        <!-- 【2】显示父组件传过来的字典类型数据  -->
        <h3>子组件:父组件传的对象{{objData}}---名字是:{{objData.name}}</h3>
      </div>
    </template>
    
    <script>
      export default{
        name:'child',
        data(){
          return {tit:'child'}
        },
        props:{
          title:[String,Number],
          msg:{
            type:String,
            required:true
          },
          age:{
            type:Number,
            default:5
            },
          objData:{//【1】父组件传值是字典时,props的特殊写法
            type:Object, //【1.1】此处数据类型必须设置为Object
            default:function(){
              return{//【1.2】这里返回值"未知"、0等可随意,目的是如果父组件没有传对应的值,就用此默认的值
                name:"未知",
                age:0,
              }
            }
          }
        }
      }
    </script>
    
    <style scoped>
    </style>
    
    

    效果:
    子组件:父组件传的对象{ "name": "flying", "age": 22 }---名字是:flying

    三、子 -> 父组件通信——子传父

    3.1简单的子--->父通信

    第1步:child.vue

    【0】此处通过点击鼠标触发的函数向父组件发消息
    【1】重点:传数据给父组件:this.$emit(键名,键值); 键名随便,父组件接收时要对应;键值此处用data里数据:this.msg

    <template>
      <div>
        <!-- 【0】此处通过点击鼠标触发的函数向父组件发消息 -->
        <button v-on:click="sendMsg">点此向父组件发消息</button>
      </div>
    </template>
    
    <script>
    
      export default{
        name:'child',
        data(){
          return{
            msg:'子组件发的消息'
          }
        },
        methods:{
          sendMsg(event){
            /*【1】重点:固定写法:this.$emit(键名,键值); 键名随便。键值此处用data里数据:this.msg
            父组件<child @sendmsg='处理函数'/>接收时@sendmsg处要对应;(把sendmsg当成一个自定义事件)
            */
            this.$emit("sendmsg",this.msg)
          }
        }
      }
    </script>
    
    <style>
    </style>
    
    

    第2步,parent.vue

    【1】用监听事件命令v-on(简写@sendmsg(此名随便写)),监听到之后触发一个函数getMsg,用它来测试子组件发来的消息
    [2]定义一个空数据用来接收子组件传来的消息
    【3】把接收到的数据传给data里的msg
    【4】展示子组件传过来的消息

    <template>
      <div>
        父组件
        <Child v-on:sendmsg='getMsg' /><!-- 【1】把sendmsg当自定义事件,所以要用监听事件命令v-on(简写@sendmsg(此名随便写)),监听到之后触发一个函数getMsg,用它来测试子组件发来的消息 -->
        {{msg}}<!-- 【4】展示子组件传过来的消息 -->
      </div>
    </template>
    
    <script>
      import Child from './child';
    
      export default{
        name:'parent',
        data(){
          return{
            msg:'' //[2]定义一个空数据用来接收子组件传来的消息
          }
        },
        components:{
          Child,
        },
        methods:{
          getMsg(data){//此处data可随便写,下面和其对应即可
            console.log(data); //测试【3】把子组件传的数据输出到控制台
            this.msg=data;//【3】把接收到的数据传给data里的msg
          }
        }
      }
    </script>
    
    <style>
    </style>
    

    效果:点击按钮之后,子组件即会发一个消息过来,父组件即接收,展示。
    在这里插入图片描述

    3.2父-->子-->父:父子组件的交互通信

    parent.vue

    【2.1】绑定data里的num(输入变<==>data.num变)
    【2.2】把data的数据转换为Number类型,(this.num - 0,即是把此数据转为数字类型)
    【2.3】向子组件传送的数据变为computed的toNum()函数处理后的值,即转为数字再传送给子组件

    <template>
      <div>
        父组件
        <!-- 【1】用监听事件命令v-on(简写@sendmsg(此名随便写)),监听到自定义事件sedmsg发生之后触发一个函数getMsg,用它来接收子组件发来的消息;
        v-bind为向子组件发送的数据; -->
        <Child v-on:sendmsg='getMsg' v-bind:num='toNum' /> <!-- 【2.3】向子组件传送的数据变为computed的toNum()函数处理后的值,即转为数字再传送给子组件 -->
        <input type="text" v-model="num" /> <!-- 【2.1】绑定data里的num(输入变<==>data.num变) -->
        {{msg}}<!-- 【5】展示子组件传过来的消息 -->
      </div>
    </template>
    
    <script>
      import Child from './child';
    
      export default{
        name:'parent',
        data(){
          return{
            msg:'', //[3]定义一个空数据用来接收子组件传来的消息
            num:5,
          }
        },
        components:{
          Child,
        },
        computed:{
          toNum(){//【2.2】把data的数据转换为Number类型,(this.num -0,即是把此数据转为数字类型)
            return this.num - 0;
          }
        },
        methods:{//【2】用函数来接收子组件消息输出到控制台进行测试
          getMsg(data){
            console.log(data);
            this.msg=data;//【4】把接收到的数据传给data里的msg
          }
        }
      }
    </script>
    
    <style>
    </style>
    
    

    child.vue

    [2.1]接收父组件传来的数据num(
    【2.2】触发发送函数,向父组件发送数据
    【2.3】调用computed里的addNum对收到父组件的数据处理处理后,再发给父组件
    【2.4】把props里收到的num进行处理的函数

    <template>
      <div>
        <!-- 【0】此处通过点击鼠标触发的函数,sendMsg通过其向父组件发消息 -->
        <button v-on:click="sendMsg">点此向父组件发消息</button> 【2.2】触发
      </div>
    </template>
    
    <script>
    
      export default{
        name:'child',
        data(){
          return{
            msg:'子组件发的消息'
          }
        },
        props:{//接收父组件数据道具
          num:{//[2.1]接收父组件传来的数据num(<child v-bind:num='toNum'/>)
            type:Number,
            default:8
          }
        },
        computed:{
          addNum(){//【2.4】把props里收到的num进行处理的函数
            return this.num*10;
          }
        },
        methods:{
          sendMsg(event){
            //【1】重点:固定写法:this.$emit(键名,键值); 键名随便,父组件接收时要对应;键值此处用data里数据:this.msg
            this.$emit("sendmsg",this.addNum) //【2.3】调用computed里的addNum对收到父组件的数据处理处理后,再发给父组件
          }
        },
    
      }
    </script>
    
    <style>
    </style>
    
    

    效果:在输入框输入数字,子组件接收,处理后,发回父组件显示
    在这里插入图片描述

  • 相关阅读:
    HTML5本地缓存localStorage和sessionStorage的操作方法收集
    Jackson使用ObjectManage#readValue传入泛型T的问题
    Java压缩字符串的方法收集
    Java读取文本文件
    IntelliJ IDEA字符串常量长度太长的问题解决:constant string too long
    Jetty错误:java.lang.IllegalStateException: Form too large 270468>200000的问题解决
    记录一次Elasticsearch线上部署后出现:org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: []的问题解决
    HTML-DEV-ToolLink(常用的在线字符串编解码、代码压缩、美化、JSON格式化、正则表达式、时间转换工具、二维码生成与解码等工具,支持在线搜索和Chrome插件。)
    cssz中<a>标签鼠标选中去除选中边框
    CentOS查看主板型号、CPU、显卡、硬盘等信息
  • 原文地址:https://www.cnblogs.com/chenxi188/p/12176839.html
Copyright © 2011-2022 走看看