Vue2.0 组件参数传递获取进阶

1、父组件访问子组件: 使用 $children 或 $refs

$children 示例

下面这段代码定义了3个组件:父组件 parent-component,两个子组件 child-component1 和 child-component2。

在父组件中,通过 this.$children 可以访问子组件。
this.$children 是一个数组,它包含所有子组件的实例。

<div id="app">
    <parent-component></parent-component>
</div>

<template id="parent-component">
    <child-component1></child-component1>
    <child-component2></child-component2>
    <input type="button" value="显示子组件的数据" v-on:click="showChildComponentData" >
</template>

<template id="child-component1">
    <h2>This is child component 1</h2>
</template>

<template id="child-component2">
    <h2>This is child component 2</h2>
</template>

<script>
    Vue.component('parent-component', {
        template: '#parent-component',
        components: {
            'child-component1': {
                template: '#child-component1',
                data: function() {
                    return {
                        msg: 'child component 111111'
                    }
                }
            },
            'child-component2': {
                template: '#child-component2',
                data: function() {
                    return {
                        msg: 'child component 222222'
                    }
                }
            }
        },
        methods: {
            showChildComponentData: function() {
                for (var i = 0; i < this.$children.length; i++) {
                    alert(this.$children[i].msg)
                }
            }
        }
    })

    new Vue({
        el: '#app'
    })
</script>
$refs 示例

组件个数较多时,我们难以记住各个组件的顺序和位置,通过序号访问子组件不是很方便。
在子组件上使用 ref 指令,可以给子组件指定一个索引 ID。

<template id="parent-component">
    <child-component1 ref="cc1"></child-component1>
    <child-component2 ref="cc2"></child-component2>
    <button v-on:click="showChildComponentData">显示子组件的数据</button>
</template>

// 在父组件中,则通过$refs.索引ID访问子组件的实例:
showChildComponentData: function() {
    alert(this.$refs.cc1.msg);
    alert(this.$refs.cc2.msg);
}

2、子组件访问父组件: 使用 $parent

下面这段代码定义了两个组件:child-component和它的父组件parent-component。
在子组件中,通过this.$parent可以访问到父组件的实例。

<div id="app">
    <parent-component></parent-component>
</div>

<template id="parent-component">
    <child-component></child-component>
</template>

<template id="child-component">
    <h2>This is a child component</h2>
    <button v-on:click="showParentComponentData">显示父组件的数据</button>
</template>

<script src="js/vue.js"></script>
<script>
    Vue.component('parent-component', {
        template: '#parent-component',
        components: {
            'child-component': {
                template: '#child-component',
                methods: {
                    showParentComponentData: function() {
                        alert(this.$parent.msg)
                    }
                }
            }
        },
        data: function() {
            return {
                msg: 'parent component message'
            }
        }
    })
    new Vue({
        el: '#app'
    })
</script>

注意:尽管可以访问父链上任意的实例,不过子组件应当避免直接依赖父组件的数据,尽量显式地使用 props 传递数据。另外,在子组件中修改父组件的状态是非常糟糕的做法,因为:

  1. 这让父组件与子组件紧密地耦合;

  2. 只看父组件,很难理解父组件的状态。因为它可能被任意子组件修改!理想情况下,只有组件自己能修改它的状态。

3、如何使用 props 来显式地传递参数。

// 父组件
<template>
  <div id="app">
    <Display></Display>
    <br>
    <Increment></Increment>
    <br>
    <p>--------------------------------------------------</p>
    <input type="text" v-model="msg" name="">
    <Child v-bind:parentmsg="msg" v-on:child-say="valueUp"></Child>
    <br>
    <p>{{childMes}}</p>
    <!-- <span style="font-family: tahoma, arial, helvetica, sans-serif; font-size: 16px">
      <p @valueUp ="recieve">{{childMes}}</p>
    </span> -->
  </div>
</template>

<script>
import Display from './display'
import Increment from './increment'
import Child from './child'

import { mapState, mapGetters, mapActions } from 'vuex'

export default {
  components: {
    Display: Display,
    Increment: Increment,
    Child: Child
  },
  data () {
    return {
      msg: 'wangzhe',
      childMes: ''
    }
  },
  computed: {
    ...mapState({
    }),
    ...mapGetters([
      'getCount'
    ])
  },
  methods: {
    ...mapActions([
      'updateMessage'
    ]),
    valueUp (mes) {
      this.childMes = mes
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>
// 子组件
<template>
  <div>
    <h4>{{parentmsg}}</h4>
    <input type="text" name="" v-model="inputValue">
    <br>
    <br>
    <p>---------------------------------------------------------</p>
    <input type="button" name="" value="点击" @click="enter">
  </div>
</template>

<script>
  import { mapState, mapGetters, mapActions } from 'vuex'
  
  export default {
    props: ['parentmsg'],
    data () {
      return {
        inputValue: ''
      }
    },
    computed: {
      ...mapState({
        age: 'count'
      }),
      ...mapGetters([
        'getCount'
      ])
    },
    methods: {
      ...mapActions([
        'updateMessage'
      ]),
      enter () {
        this.$emit('child-say', this.inputValue)
      }
    }
  }
</script>

推荐阅读更多精彩内容