美文网首页
vue 组件间的传值

vue 组件间的传值

作者: chulijun | 来源:发表于2019-09-26 12:57 被阅读0次

    引用官网的一句话:父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息


    image.png

    1.父组件向子组件传值

    在子组件中定义props数组添加属性,父组件可以直接给props中的属性传值

    • 父组件—传值—>子组件
      1、子组件绑定父组件的数据
      v-bind:post="post"
      2、子组件用props接收
      props: ['post'],

    • 父组件—监听—>子组件
      1、监听(父)
      v-on:enlarge-text123=“执行的事件"
      2、发送(子)
      v-on:click="$emit('enlarge-text123')"

    具体代码实现

    postDemo.js

    import Vue from 'vue'
    
    Vue.component('blog-post', {
        props: ['post'],
        template: `
        <div class="blog-post">
          <h3>{{ post.title }}</h3>
          <button v-on:click="$emit('enlarge-text')">
                    Enlarge text
                </button>
          <div v-html="post.content"></div>
        </div>
    })
    

    vue_global_api.vue

    <template>
        <div id="vue_global_api">
            <div id="components-demo">
                <!-- 
                    v-bind:key 不传有警告
                    v-bind:post post是组件内接收的参数名
                 -->
                <!-- <blog-post v-for="post in posts" v-bind:post="post" v-bind:key="post.id" v-on:enlarge-text="onEnlargeText"></blog-post> -->
                <div :style="{ fontSize: postFontSize + 'em' }">
                    <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-on:enlarge-text="postFontSize += 0.1"></blog-post>
                </div>
                <div :style="{ fontSize: postFontSize + 'em' }">
                    <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-on:enlarge-text="postFontSizeAction"></blog-post>
                </div>
            </div>
        </div>
    </template>
    <article class="_2rhmJa" style="box-sizing: border-box; display: block; font-weight: 400; line-height: 1.8; margin-bottom: 20px;">
    
    
    <script>
        import {
            postDemo
        } from '../js/postDemo.js'
        export default {
            el: 'vue_global_api',
            data() {
                return {
                    posts: [{
                            id: 1,
                            title: 'My journey with Vue'
                        },
                        {
                            id: 2,
                            title: 'Blogging with Vue'
                        },
                        {
                            id: 3,
                            title: 'Why Vue is so fun'
                        }
                    ],
                    data: {
                        title: "this.title",
                        message: "this.message"
                    },
                    postFontSize: 1
                }
            },
            methods: {
                postFontSizeAction() {
                    this.postFontSize += 0.1
                }
            }
        }
    </script>
    <style>
    </style>
    
    

    2.子组件向父组件传值

    子组件可以通过调用内建的 $emit 方法 并传入事件名称来触发一个事件

    通过事件向父组件发送信息

    • 子组件中EnFontsize.vue中$emit
     <button @click="$emit('enlarge-text')">Enlarge text</button>
    
    • 父组件中:
    <template>
      <div id="app">
        <div :style="{ fontSize: postFontSize + 'em' }">
          <div v-for="post in posts" v-bind:key="post.id" v-bind:post="post">
            <span>{{post.id}}</span>
            <span>{{post.title}}</span>
            <EnFontsize v-on:enlarge-text="postFontSize += 0.1"></EnFontsize>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import EnFontsize from "./components/EnFontsize";
     
    export default {
      name: "App",
      data: function() {
        return {
          posts: [
            { id: 1, title: "the title is..." },
            { id: 2, title: "the title is..." }
          ],
          postFontSize: 1
        };
      },
      components: {
        EnFontsize
      }
    };
    </script>
    

    使用事件抛出一个值

    • 子组件中使用 $emit 的第二个参数来提供这个值:

    <button @click="$emit('enlarge-text123', 0.1)">Enlarge text</button>

    • 父组件中可以通过 $event 访问到被抛出的这个值:
     <EnFontsize v-on:enlarge-text123="postFontSize += $event"></EnFontsize>
    或者,如果这个事件处理函数是一个方法:
    <!-- <EnFontsize v-on:enlarge-text="postFontSize+=$event"></EnFon>-->
        <EnFontsize v-on:enlarge-text="onEnlargeText"></EnFontsize>
    那么这个值将会作为第一个参数传入这个方法:
    methods: {
      onEnlargeText: function (enlargeAmount) {
        this.postFontSize += enlargeAmount
      }
    }
    
    注意:这里是自动接收这个值并传给函数作为第一个参数,虽然没有使用$event接收
    

    3.非父子组件进行传值

    非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果。

    • 公共bus.js
    //bus.js
    import Vue from 'vue'
    export default new Vue()
    
    • 组件A:
    A组件:
    <template>
      <div>
        <span>{{elementValue}}</span>
        <input type="button" value="点击触发" @click="elementByValue">
      </div>
    </template>
    <script>
      // 引入公共的bug,来做为中间传达的工具
      import Bus from './bus.js'
      export default {
        data () {
          return {
            elementValue: 4
          }
        },
        methods: {
          elementByValue: function () {
            Bus.$emit('val', this.elementValue)
          }
        }
      }
    </script>
    
    • 组件B:
    <template>
      <div>
        B组件:
        <input type="button" value="点击触发" @click="getData">
        <span>{{name}}</span>
      </div>
    </template>
    <script>
      import Bus from './bus.js'
      export default {
        data () {
          return {
            name: 0
          }
        },
        mounted: function () {
          var vm = this
          // 用$on事件来接收参数
          Bus.$on('val', (data) => {
            console.log(data)
            vm.name = data
          })
        },
        methods: {
          getData: function () {
            this.name++
          }
        }
      }
    </script>
    

    非父子组之间的传值方式:1.创建中间仓库。2,缓存 3,vuex

    单向数据流

    所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

    额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

    • 这里有两种常见的试图改变一个 prop 的情形:
      1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
    props: ['initialCounter'],
    data: function () {
      return {
        counter: this.initialCounter
      }
    }
    
    • 这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
    props: ['size'],
    computed: {
     // 计算属性的 getter
      normalizedSize: function () {
     // `this` 指向 vm 实例
        return this.size.trim().toLowerCase()
      }
    }
    

    注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。

    相关文章

      网友评论

          本文标题:vue 组件间的传值

          本文链接:https://www.haomeiwen.com/subject/yciguctx.html