在vue中,组件是最重要的组合部分,官方中定义组件为可复用的vue实例,分为全局组件和局部组件,接下来通过实例来分别演示两种不同的组件。

1.1.全局组件

全局组件可以在任意Vue实例下使用。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  5. <script>
  6. Vue.component('mycomponent', {
  7. template: '<h3>我是全局组件</h3>'
  8. });
  9. var vm = new Vue({
  10. el: '#app',
  11. });
  12. </script>

通过上面的例子,我们可以总结出全局组件的使用步骤:

  1. 使用vue.component()注册组件,需要提供2个参数:组件的标签名和组件构造器。
  2. vue.component()内部会调用组件构造器,创建一个组件实例
  3. 将组建挂载到某个vue实例下。

    注意:一个组件的template部分,必须要包裹在一个根容器中。

因为组件是可复用的vue实例,所以它们也能有data、computed、watch、methods以及生命周期钩子等。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  5. <script>
  6. Vue.component('mycomponent', {
  7. template: `<div>
  8. <h3>我是全局组件</h3>
  9. {{num}} <button @click="add">加</button>
  10. </div>`,
  11. data(){
  12. return {
  13. num:1
  14. }
  15. },
  16. methods:{
  17. add(){
  18. this.num++;
  19. }
  20. }
  21. });
  22. var vm = new Vue({
  23. el: '#app',
  24. });
  25. </script>

上面代码中有两个注意事项:

  1. 组件模板的内容,可以写在一对反引号中(``),这样就可以不使用字符串拼接的形式了。
  2. 一个组件的data选项必须是一个函数,该函数返回一个对象。

1.2.局部组件

如果不需要全局注册,或者是让组件使用在其它组件内,可以用选项对象的components属性实现局部注册。 因此我们可以将上面的全局组件改为局部组件。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  5. <script>
  6. let obj = {
  7. template: `<div>
  8. <h3>我是局部组件</h3>
  9. {{num}} <button @click="add">加</button>
  10. </div>`,
  11. data(){
  12. return {
  13. num:1
  14. }
  15. },
  16. methods:{
  17. add(){
  18. this.num++;
  19. }
  20. }
  21. };
  22. var vm = new Vue({
  23. el: '#app',
  24. components:{ //声明局部组件
  25. mycomponent:obj
  26. }
  27. });
  28. </script>

1.3.组件模板

如果组件中的template内容过多,那么可以使用组件模板来声明template中的内容。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <!-- 组件模板 -->
  5. <template id="mytemplate">
  6. <div>
  7. <h3>我是局部组件</h3>
  8. {{num}} <button @click="add"></button>
  9. </div>
  10. </template>
  11. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  12. <script>
  13. let obj = {
  14. template: '#mytemplate', //使用选择器应用组件模板
  15. data() {
  16. return {
  17. num: 1
  18. }
  19. },
  20. methods: {
  21. add() {
  22. this.num++;
  23. }
  24. }
  25. };
  26. var vm = new Vue({
  27. el: '#app',
  28. components: { //声明局部组件
  29. mycomponent: obj //组件名:组件实例
  30. }
  31. });
  32. </script>

2.父子组件

当我们继续在组件中写组件,形成组件嵌套的时候,就是我们所说的父子组件了。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <h3>我是父组件</h3>
  7. <!-- 在父组件中使用子组件 -->
  8. <subcomponents></subcomponents>
  9. </div>
  10. </template>
  11. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  12. <script>
  13. let obj = {
  14. template: '#mytemplate',
  15. data() {
  16. return {}
  17. },
  18. components:{ //声明子组件
  19. subcomponents:{
  20. template:`<div>我是子组件</div>`
  21. }
  22. }
  23. };
  24. var vm = new Vue({
  25. el: '#app',
  26. components: { //声明局部组件
  27. mycomponent: obj //组件名:组件实例
  28. }
  29. });
  30. </script>

3.组件之间的通信

组件与组件之间是可以互相通信的。包括父子组件之间、兄弟组件之间等等,都可以互相通信。 下面只讨论父子组件之间通信问题。

3.1.子组件获取父组件数据

在vue中,组件实例的作用域是孤立的,默认情况下,父子组件的数据是不能共享的,也就是说,子组件是不能直接访问父组件的数据的。为此,vue给我们提供了一个数据传递的选项prop,用来将父组件的数据传递给子组件。具体使用如下:

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <h3>我是父组件</h3>
  7. <subcomponents msg="hello world!"></subcomponents>
  8. </div>
  9. </template>
  10. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  11. <script>
  12. let obj = {
  13. template: '#mytemplate',
  14. data() {
  15. return {}
  16. },
  17. components:{
  18. subcomponents:{
  19. template:`<div>我是子组件,我能获取父组件传递的数据:{{msg}}</div>`,
  20. props:['msg']
  21. }
  22. }
  23. };
  24. var vm = new Vue({
  25. el: '#app',
  26. components: { //声明局部组件
  27. mycomponent: obj //组件名:组件实例
  28. }
  29. });
  30. </script>

上面实例中,子组件获取父组件传递的数据的步骤为:

  1. 在子组件标签中,声明 msg 属性,属性值即为父组件向子组件传递的值。
  2. 在子组件中,使用props选项,声明接收父组件向子组件传递值的载体,即 ‘msg’ 。
  3. 子组件中就可以使用 msg 获取父组件向子组件传递的值了。

也可以使用 v-bind 绑定子组件标签属性,这样就可以将父组件data数据传递个子组件了。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <h3>我是父组件</h3>
  7. <subcomponents :msg="welcome"></subcomponents>
  8. </div>
  9. </template>
  10. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  11. <script>
  12. let obj = {
  13. template: '#mytemplate',
  14. data() {
  15. return {
  16. welcome:'hello world!'
  17. }
  18. },
  19. components:{
  20. subcomponents:{
  21. template:`<div>我是子组件,我能获取父组件传递的数据:{{msg}}</div>`,
  22. props:['msg']
  23. }
  24. }
  25. };
  26. var vm = new Vue({
  27. el: '#app',
  28. components: { //声明局部组件
  29. mycomponent: obj //组件名:组件实例
  30. }
  31. });
  32. </script>

3.2.父组件获取子组件数据

和上面不一样的是,父组件想要获取子组件的数据时,需要子组件通过emit主动将自己的数据发送给父组件。

  1. <div id="app">
  2. <mycomponent></mycomponent>
  3. </div>
  4. <template id="mytemplate">
  5. <div>
  6. <h3>我是父组件,接收子组件传递过来的数据:{{msg}}</h3>
  7. <subcomponents @childmsg="get" msg="hello world!"></subcomponents>
  8. </div>
  9. </template>
  10. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  11. <script>
  12. let obj = {
  13. template: '#mytemplate',
  14. data() {
  15. return {
  16. msg:''
  17. }
  18. },
  19. methods:{
  20. get(msg) {
  21. this.msg = msg;
  22. }
  23. },
  24. components: {
  25. subcomponents: {
  26. template: `<div>
  27. 我是子组件,我能获取父组件传递的数据:{{msg}}
  28. <input type="button" value="给父组件发数据" @click="send">
  29. </div>`,
  30. props: ['msg'],
  31. data() {
  32. return {
  33. message: '我是子组件的数据'
  34. }
  35. },
  36. methods: {
  37. send() {
  38. this.$emit('childmsg', this.message);
  39. }
  40. }
  41. }
  42. }
  43. };
  44. var vm = new Vue({
  45. el: '#app',
  46. components: { //声明局部组件
  47. mycomponent: obj //组件名:组件实例
  48. }
  49. });
  50. </script>

首先,我们需要在子组件中触发一个主动发送数据的事件,上面的例子中是一个点击事件send
其次,在点击事件中使用emit方法,这个emit接收两个参数:传递数据的事件和需要传递的数据,这个传递数据的事件也是自定义的;
然后在父组件中引用子组件,并在引用的子组件中使用on监听上一步传递数据的事件,上面的例子中是childmsg
最后在父组件中使用这个事件,这个事件带有一个参数,就是从子组件发送过来的数据。
[

](https://null_688_6639.gitee.io/javase/15Vue/03.%E7%AC%AC%E4%B8%89%E7%AB%A0Vue%E8%BF%9B%E9%98%B6.html)