vue 组件间的传值

2019-09-26  本文已影响0人  chulijun

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


image.png

1.父组件向子组件传值

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

具体代码实现

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 方法 并传入事件名称来触发一个事件

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

 <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>

使用事件抛出一个值

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

 <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
import Vue from 'vue'
export default new Vue()
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>
<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 会在浏览器的控制台中发出警告。

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}
props: ['size'],
computed: {
 // 计算属性的 getter
  normalizedSize: function () {
 // `this` 指向 vm 实例
    return this.size.trim().toLowerCase()
  }
}

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

上一篇下一篇

猜你喜欢

热点阅读