组件:把页面中相同的功能封装成一个组件,以后再有这样的功能,使用这个组件就会有对应的功能,用组件的思想开发可以大幅度提升开发效率,提高代码的可复用度和可维护性

在 Vue 中,创建组件有两种
全局组件:创建之后,所有的 Vue 实例都可以使用这个组件
局部组件:只能在注册的实例中使用局部组件

一、全局组件

创建全局组件:Vue.component(componentName, config);

  1. componentName 组件名字,可以是驼峰命名,也可以连字符;
  2. config 是一个对象,和创建 Vue 实例的配置对象一样;
  3. 在 html 或者模板中使用组件时,只能写连字符 component-name 的形式
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <!--使用组件:把驼峰命名法变成连字符形式;使用组件就需要写一个自定义标签;-->
  10. <handsome-man></handsome-man>
  11. </div>
  12. <div id="app2">
  13. <handsome-man></handsome-man>
  14. <handsome-man />
  15. </div>
  16. <script src="vue.js"></script>
  17. <script>
  18. // 创建一个全局组件
  19. Vue.component('handsomeMan', {
  20. template: `<div @click="fn">{{msg}}</div>`,
  21. data() { // 组件化 data 需要写一个函数,在函数中 return 一个对象,把数据写在 return 后面的对象中
  22. return {
  23. msg: '小飞'
  24. }
  25. },
  26. methods: {
  27. fn() {
  28. console.log('Muscle');
  29. }
  30. }
  31. });
  32. // 使用全局组件
  33. let vm1 = new Vue({
  34. el: '#app',
  35. data: {}
  36. });
  37. let vm2 = new Vue({
  38. el: '#app2',
  39. data: {}
  40. });
  41. // 每个组件都是一个 Vue 的实例,创建 Vue 实例时使用的属性,创建组件时,这些属性都可以有;template data filter computed methods watch 生命周期的钩子函数 组件都可以有;
  42. </script>
  43. </body>
  44. </html>

二、局部组件

局部组件使用步骤

  1. 创建组件
  2. 注册组件
  3. 使用组件 ```html <!DOCTYPE html>


  1. <a name="wv8pA"></a>
  2. ## 三、组件嵌套
  3. ```html
  4. <!doctype html>
  5. <html lang="en">
  6. <head>
  7. <meta charset="UTF-8">
  8. <meta name="viewport"
  9. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  10. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  11. <title>Document</title>
  12. </head>
  13. <body>
  14. <div id="app"></div>
  15. <script src="vue.js"></script>
  16. <script type="module">
  17. import son from './son.js';
  18. let vm = new Vue({
  19. template: `<div>{{gen}} <son></son></div>`,
  20. data: {
  21. gen: 'Parent'
  22. },
  23. components: {
  24. son
  25. }
  26. });
  27. vm.$mount('#app');
  28. </script>
  29. </body>
  30. </html>

四、组件间的通信

1. 父传子

使用 props

  1. 在使用子组件时,在子组件标签行内动态绑定一个属性,如 :outermsg, 属性右侧引号中是一个变量,这个变量就绑定了父组件中的数据;写在子组件行内的属性,如 outermsg,叫做一个 props;
  2. 在子组件的 props 属性中注册当前的 props;例如,props: [‘outermsg’]
  3. 使用 props,vm 最终会代理所有的 props,所以和使用 data 中的数据相同的方式来使用 props;但是不能修改!
  4. 使用 props 动态绑定父组件的数据,当父组件的数据发生变化时,子组件收到数据自动跟着变化;

父传子用 props;
Vue 父子组件通信是单向数据流,数据只能是父组件传给子组件,子组件不能直接修改父组件的数据;
单向数据流,父组件的数据发生变化时,子组件收到的数据自动发生变化;
当子组件想修改父组件的数据时,子组件要通知父组件,让父组件去修改数据,父组件修改后,子组件就会自动获得到最新的数据;

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app">
  9. <!--<div> 写在根 DOM 元素下面的东西就是模板,和 template 属性一样的作用
  10. <input type="text" v-model="pmsg">
  11. <son :outermsg="pmsg" double="pmsg"></son>
  12. </div>-->
  13. </div>
  14. <script src="vue.js"></script>
  15. <script>
  16. let son = {
  17. template: `<div>{{outermsg}} | {{double}}<button @click="fn">修改</button></div>`,
  18. data() {
  19. return {
  20. msg: 'hello'
  21. }
  22. },
  23. props: ['outermsg', 'double'],
  24. methods: {
  25. fn() {
  26. // console.log(this.outermsg);
  27. // this.outermsg = '呵呵'; // 报错
  28. }
  29. }
  30. };
  31. let vm = new Vue({
  32. template: `<div><input type="text" v-model="pmsg"><son :outermsg="pmsg" double="pmsg"></son></div>`,
  33. el: '#app',
  34. data: {
  35. pmsg: 'msg from parent'
  36. },
  37. components: {
  38. son
  39. }
  40. });
  41. </script>
  42. </body>
  43. </html>

2. 子传父

当子组件要修改父组件数据时,要通知父组件,让父组件修改数据;
子传父:

  1. 父组件在引用子组件的地方,要监听一个自定义事件(事件名可以用连字符,但是尽量不用驼峰命名法),并且给这个事件绑定一个事件函数,这个函数有一个形参,用来接收子组件传递过来的数据;
  2. 子组件中,当子组件想要修改来自父组件的数据时,用 this.$emit() 触发父组件监听的自定义事件,同时传入数据;
  3. 当自定义事件被子组件触发时,会执行事件函数,我们把修改数据的逻辑写在这个函数就可以了;

    子传父通过事件,父组件监听事件,子组件触发事件;

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <div id="app"></div>
  9. <script src="vue.js"></script>
  10. <script>
  11. let son = {
  12. template: `<div>{{outermsg}} | {{double}}<button @click="fn">修改</button></div>`,
  13. data() {
  14. return {
  15. msg: 'hello'
  16. }
  17. },
  18. props: ['outermsg', 'double'],
  19. methods: {
  20. fn() {
  21. // 在这里通知父组件修改数据,即在这里触发事件
  22. this.$emit('change-msg', '呵呵哒'); // this.$emit(事件名, 传递给父组件的数据)
  23. }
  24. }
  25. };
  26. let vm = new Vue({
  27. template: `<div><input type="text" v-model="pmsg">
  28. <son :outermsg="pmsg" double="pmsg" @change-msg="changeMsg"></son></div>`,
  29. el: '#app',
  30. data: {
  31. pmsg: 'msg from parent'
  32. },
  33. components: {
  34. son
  35. },
  36. methods: {
  37. changeMsg(val) {
  38. // val 子组件触发事件时传入的数据
  39. this.pmsg = val;
  40. // console.log(val);
  41. }
  42. }
  43. });
  44. </script>
  45. </body>
  46. </html>

1-webpack.config.jscxk.jsgrandson.jsmabin.jsson.jsvue.js