vue组件、组件传值

403 阅读2分钟

组件

组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝 这就是为什么组件里的data是方法的原因

组件全局注册和局部注册

全局注册

Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })

new Vue({ el: '#app' })

<div id="app">
  <component-a></component-a>
  <component-b></component-b>
  <component-c></component-c>
</div>

局部注册

var ComponentA = { /* ... */ }
var component-b = { /* ... */ }

然后在 components 选项中定义你想要使用的组件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b'
  }
})

其他文件注册组件

import ComponentA from './ComponentA'
import ComponentC from './ComponentC'

export default {
  components: {
    ComponentA,
    ComponentC
  },
  // ...
}

现在 ComponentA 和 ComponentC 都可以在 ComponentB 的模板中使用了

每个组件必须只有一个根元素

<div class="blog-post">
  <h3>{{ title }}</h3>
  <div v-html="content"></div>
</div>

扩展:想要将一个对象的所有属性全部传入,可以使用不带参数的 v-bind (取代 v-bind:prop-name)。

例如,对于一个给定的对象 post

post: {
  id: 1,
  title: 'My Journey with Vue'
}
下面的模板:

<blog-post v-bind="post"></blog-post>
等价于:

<blog-post
  v-bind:id="post.id"
  v-bind:title="post.title"
></blog-post>

组件传值

父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。

父向子传值使用props

props第一种写法 数组式 props: ['msg']

template: "<div><h1>{{msg}}</h1></div>"

props第二种写法 对象式 对象里面就是键值对

props: {
         msg:{
         required:true/false   //代表改变是否必须
         type:String/Array/Number/Object //传入的变量的类型检查
              }

父组件

<template>
  <div>
    父组件:
    <input type="text" v-model="name">
    <br>
    <br>
    <!-- 引入子组件 -->
    <child :inputName="name"></child>
  </div>
</template>
<script>
  import child from './child'
  export default {
    components: {
      child
    },
    data () {
      return {
        name: ''
      }
    }
  }
</script>

子组件:

<template>
  <div>
    子组件:
    <span>{{inputName}}</span>
  </div>
</template>
<script>
  export default {
    // 接受父组件的值
    props: {
      inputName: String,
      required: true
    }
  }
</script>

子向父传值

子组件

<template>
  <div>
    子组件:
    <span>{{childValue}}</span>
    <!-- 定义一个子组件传值的方法 -->
    <input type="button" value="点击触发" @click="childClick">
  </div>
</template>
<script>
  export default {
    data () {
      return {
        childValue: '我是子组件的数据'
      }
    },
    methods: {
      childClick () {
        // childByValue是在父组件on监听的方法
        // 第二个参数this.childValue是需要传的值
        this.$emit('childByValue', this.childValue)
      }
    }
  }
</script>

父组件

<template>
  <div>
    父组件:
    <span>{{name}}</span>
    <br>
    <br>
    <!-- 引入子组件 定义一个on的方法监听子组件的状态-->
    <child v-on:childByValue="childByValue"></child>
  </div>
</template>
<script>
  import child from './child'
  export default {
    components: {
      child
    },
    data () {
      return {
        name: ''
      }
    },
    methods: {
      childByValue: function (childValue) {
        // childValue就是子组件传过来的值
        this.name = childValue
      }
    }
  }
</script>

兄弟传值

第一种 a传给父亲,父亲在传给b

第二种 bus总线传值

1、在main.js中创建bus总线

Vue.prototype.bus = new Vue()

2、在子组件A中,通过bus总线抛出信息和值。this.bus就是Vue实例,$emit也是上面的方法

@click=“handle”

methods:{
	handle(e) {
	this.bus.$emit('message',数据)
}
}

3、在子组件B中,在created或mounted等生命周期函数上,监听那个事件和获取那个值。

created() {
	this.bus.$on('busEvent',res => {
	this.busValue = res
	
})
}

完整代码

公共bus.js

//bus.js
import Vue from 'vue'
export default new Vue()

组件A:

<template>
  <div>
    A组件:
    <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>1234567891011121314151617181920212223

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

----------------------------------------------------------------------------------------------

另附上两种子组件调用父组件方法

第一种方法是直接在子组件中通过this.$parent.event来调用父组件的方法

父组件
<template>
  <div>
    <child></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>

子组件
<template>
  <div>
    <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$parent.fatherMethod();
      }
    }
  };
</script>

第二种是父组件把方法传入子组件中,在子组件里直接调用这个方法

父组件
<template>
  <div>
    <child :fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>
子组件
<template>
  <div>
    <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default {
    props: {
      fatherMethod: {
        type: Function,
        default: null
      }
    },
    methods: {
      childMethod() {
        if (this.fatherMethod) {
          this.fatherMethod();
        }
      }
    }
  };
</script>