• 单文件组件.vue---父子组件通信


        每一个.vue 文件就是一个 组件,组件和组件相互组合,就成了一个应用,这就涉及到的组件和组件之间的通信,最常用的就是父子之间的通信。在vue 中, 在一个组件中通过 import 引入另一个组件,这个组件就是父组件,被引入的组件就是子组件。

    【一】父组件→子组件

    (1)父组件传递数据

     在vue-cli 项目中,src 文件夹下有一个App.vue 文件,它的script标签中

    import HelloDemo from './components/HelloDemo'

        那么 App.vue 就是父组件,components 文件夹下的HelloDemo.vue 就是子组件。父组件通过props 向子组件传递数据,子组件通过自定义事件向父组件传递数据。

     父组件向子组件传值, 它主要是通过元素的属性进行的. 在App.vue 的template中,有一个 

    <hello-demo></hello-demo>

        这就是我们引入的子组件.  给其添加属性如

    <hello-demo :mes-father="mesFather"></hello-demo>

       父组件数据mesFather为

    return {
            'mesFather':'message from father,我是来自父组件的数据'
          }

        父组件将数据传递进去,子组件需要接收才能使用. 怎样接收呢?

    (2)子组件接收数据

        在HelloDemo.vue 中, export default 后面的对象中,添加一个字段props, 它是一个数组, 专门用来接收父组件传递过来的数据. props: ["mesFather"], 这里定义了mesFather 字符串, 和父组件中定义的元素的属性一一对应。

      export default{
        props:['mesFather']
      }

        但是我们在父组件,就是在 <hello-demo> 元素中定义的属性是mes-father, 没有一一对应啊?  这主要是因为,在html 元素中大小写是不敏感的。

        如果我们写

    <hello-demo :mesFather="mesFather"></hello-demo>

        里面的mesFather  就会转化成mesfather, 相当于我们向子组件传递了一个mesfather数据, 如果在js 文件中,我们定义 props: ["mesFather"],我们是接受不到数据的,因为js 是区分大小写的, 所以只能写成props: ["mesfather"]。

        但是在js 文件中,像这种两个单词拼成的数据,我们习惯用驼峰命名法,所以vue 做了一个转化,如果在组件中属性是 - 表示,它 自动会转化成驼峰式。  传进来的数据是mes-father, 转化成mesFather, 我们在js 里面写mesFather, 一一对应,子组件可以接受到组件。 props 属性是和data, methods 属性并列的,属同一级别。 props 属性里面定义的变量,在 子组件中的template 中可以直接使用。

        App.vue 的template 更改如下:

    <hello-demo :mes-father="mesFather"></hello-demo>import HelloDemo from './components/HelloDemo'
    export default{
      name: 'App',
      data(){
    return {
    'mesFather':'message from father,我是来自父组件的数据'
    }
    },
    components: {HelloDemo} 
    }

        HelloDemo.vue组件:

    <template>
      <div>
        <h1>Hello页面</h1>
        <p>{{mesFather}}</p>
      </div>
    </template>
    <script>
      export default{
        props:['mesFather']
      }
    </script>

        这时,在页面中看到 ‘message from father,我是来自父组件的数据’ 字样,父元素向子元素传递数据成功。

    【二】子组件→父组件

        子组件向父组件传递数据,需要用到自定义事件。 例如,我们在HelloDemo.vue ,写入一个input, 接收用户输入,我们想把用户输入的数据传给父组件。这时,input 需要先绑定一个keypress 事件,获取用户的输入,同时还要发射自定义事件,如valueUp, 父组件只要监听这个自定义事件,就可以知道子组件要向他传递数据了。子组件在发射自定义事件时,还可以携带参数,父组件在监听该事件时,还可以接受参数,参数就是要传递的数据。

     在 HelloDemo.vue的template中,添加一个input输入框,给它一个v-model 获取用户的输入,再添加keypress的事件,用于发射事件和传输数据。script 中添加data,定义变量来获取用户的输入,添加methods 来处理keypress事件的处理函数enter, 整个HelloDemo.vue 文件如下

       (1)子组件发射事件和传输数据

    <template>
      <div style="margin: 10px;border: 1px solid red;padding: 10px;background: rgba(0,0,0,0.3)">
        <h1>Hello页面</h1>
        <p>{{message}}</p>
        <p>{{mesFather}}</p>
        子组件输入框:<input type="text" placeholder="请输入..." v-model="inputValue" v-on:keypress.enter="enterFn"/>
        输入元素伪:{{inputValue}}
      </div>
    </template>
    <script>
      export default{
        props:['mesFather'],
        data(){
          return {
            message:'我是Hello本页面展示信息',
            inputValue:''// 添加inputValue,用户输入绑定到inputValue变量,从而获取用户输入
          }
        },
        methods:{
          enterFn(val){
            this.$emit('valueUp',this.inputValue);
            //子组件发射自定义事件valueUp, 并携带要传递给父组件的值
            //如果要传递给父组件很多值,这些值要作为参数依次列出 如 this.$emit('valueUp', this.inputValue, this.mesFather);
          }
        }
      }
    </script>

    结果:

        

    (2)父组件监听发射事件和展示接收数据

        在App.vue 中, template中hello-demo组件绑定一个自定义事件,@valueUp =“receive”, 用于监听子组件发射的事件,再写一个 p 元素,用于展示子组件传递过来的数据,<p>子组件传递过来的数据 {{ childMes }}</p>

        相应地,在scrpit中,data 中,定义一个变量childMes, 并在 methods 中,定义一个事件处理函数reciever。整个App.vue修改如下:

    <!--添加自定义事件valueUp-->
    <hello-demo :mes-father="mesFather" v-on:valueUp="recieve"></hello-demo> <!-- p元素,用于展示子组件传递过来的数据 -->
    <p>子组件传递过来的数据 {{childMes}}</p> import HelloDemo from './components/HelloDemo' export default{ name: 'App', data(){ return { 'mesFather':'message from father,我是来自父组件的数据', childMes:'' } }, components: {HelloDemo}, methods:{ recieve(mes){ // recieve 事件需要设置参数,这些参数就是子组件传递过来的数据,因此,参数的个数,也要和子元素传递过来的一致。 this.childMes = mes; } } }

        这时在input中输入内容,然后按enter键,就以看到子组件传递过来的数据,子组件向父组件传递数据成功。

    结果:

    (3)分析:

        ①子组件input发射事件

    <input type="text" placeholder="请输入..." v-model="inputValue" v-on:keypress.enter="enterFn"/>

        当在input输入框中输入数据,并按enter键时,它会触发keypress.enter事件,从而调用事件处理函数enterFn

        在enterFn 中, 我们发射了一个事件valueUp, 并携带了一个参数

    methods:{
          enterFn(val){
            this.$emit('valueUp',this.inputValue);
            //子组件发射自定义事件valueUp, 并携带要传递给父组件的值
            //如果要传递给父组件很多值,这些值要作为参数依次列出 如 this.$emit('valueUp', this.inputValue, this.mesFather);
          }
        }

        ②父组件监听事件、接收展示数据

    <hello-demo :mes-father="mesFather" v-on:valueUp="recieve"></hello-demo>

        由于在父组件中, 我们绑定valueUp 事件,所以父组件在时刻监听valueUp 事件, 当子组件发射value 事件时,父组件立刻捕获到,并立即调用它的回调函数receive, 在receive 中,我们获取到子组件传递过来的数据,并赋值了父组件data 中的变量childMes, 由于data 数据发生变化,从而触发dom更新,页面中就显示子组件传递过来的内容。

    <!-- p元素,用于展示子组件传递过来的数据 -->
    <p>子组件传递过来的数据 {{childMes}}</p>
    
    data(){
      return {
        childMes:''
      }
    }

    (4)props验证

        在子组件中, props 最好的写法是props 验证,我们在子组件HelloDemo.vue中写 props:['mesFather'], 只是表达出,它接受一个参数mesFather, 如果写成props 验证,不仅能表达出它需要什么参数,还能表达参数类型,并且如有错误,vue 会做出警告。现在把props 改成props 验证的写法, HelloDemo.vue 中的js中的props修改如下:

    props:{
          'mesFather':{
            type: String,
            default: 'from father来自父级的数据',
            required:true
          }
        }

        如果是组件与组件之间的通信非常复杂,不光是父子组件,还有兄弟组件,那就需要用到状态管理vuex,稍后讲解。

    .

  • 相关阅读:
    微信公众平台订阅号和服务号和企业号的区别
    微信支付现金红包接口说明及应用实例代码
    Android开发环境配置
    在自己的android工程中使用actionbarsherlock以及slidingmenu
    android个推推送平台的使用
    android网络
    android String 类型转换成UTF-8格式
    【转】android神一样的模拟器——genymotion
    基于百度云推送的实时通信客户端实现(三)
    基于百度云推送的实时通信客户端实现(二)
  • 原文地址:https://www.cnblogs.com/fightjianxian/p/10674462.html
Copyright © 2020-2023  润新知