Vue组件化 模板 语法糖 函数 父子组件通信

2023-06-25 23:26:41 浏览数 (1)

@TOC

1 注册组件的基本步骤

  • 创建爱你组件构造器:Vue.extends()
  • 注册组件:Vue.component()
  • 使用组件

2 组件的基本使用

代码语言:html复制
<div id="app">
<!-- 3 使用组件 -->
   <my-cpn></my-cpn>
   <my-cpn></my-cpn>
   <my-cpn></my-cpn>
</div>

<script src="../js/vue.js"></script>
<script>
  // 1 创建组件构造器对象
  const cpnConstructor = Vue.extend({
    template: `
        <div>
        <h2>标题</h2>
        <p>哈哈哈</p>
        </div>
    `
  })

  // 2 注册组件
  Vue.component('my-cpn', cpnConstructor)

  const app = new Vue({
    el: '#app',
    data: {
      message: "你好,有勇气的牛排"
    }
  })
</script>

3 全局组件和局部组件

代码语言:html复制
<script src="../js/vue.js"></script>
<script>
  // 1 创建组件构造器
  const cpnC = Vue.extend({
    template: `
        <div>
          <h2>标题</h2>
          <p>内容</p>
        </div>
    `
  })

  // 2 组件注册(全局组件: 意味着可以在多个Vue实例下面使用)
  // Vue.component('cpn', cpnC)

  // Vue实例1
  const app = new Vue({
    el: '#app',
    data: {
      message: "你好,有勇气的牛排"
    },
    // 局部组件
    components:{
      // cpn使用组件时的标签名
      cpn:cpnC
    }
  })
  // Vue实例2
  const app2 = new Vue({
    el: '#app2'
  })
</script>

4 父组件和子组件

代码语言:html复制
<div id="app">
    <cpn2></cpn2>
</div>

<script src="../js/vue.js"></script>
<script>
  // 1 创建爱你第1个组件构造器(子组件)
  const cpnC1 = Vue.extend({
    template: `
        <div>
          <h2>标题1</h2>
          <p>666</p>
        </div>
      `
  })

  // 2 创建爱你第2个组件构造器(父组件)
  const cpnC2 = Vue.extend({
    template: `
        <div>
          <h2>标题2</h2>
          <p>777</p>
          <cpn1></cpn1>
        </div>

      `,
    components: {
      cpn1: cpnC1
    }
  })

  // root组件
  const app = new Vue({
    el: '#app',
    data: {
      message: "你好,有勇气的牛排"
    },
    components: {
      cpn2: cpnC2
    }
  })
</script>

5 注册组件语法糖

主要省区了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替

代码语言:html复制
<script>
  // 1 全局组件注册的语法糖
  // 1 创建组件构造器
  // const cpn1 = Vue.extend()

  // 2 组件注册(全局方式)
  Vue.component('cpn1', {
    template: `
        <div>
          <h2>标题1</h2>
          <p>666</p>
        </div>
      `
  })
  const app = new Vue({
    el: '#app',
    data: {
      message: "你好,有勇气的牛排"
    },
    components: {
      'cpn2': {
        template: `
            <div>
              <h2>标题2</h2>
              <p>777</p>
            </div>
        `
      }
    }
  })
</script>

6 组件模板分离写法 组件数据存放

存放

  • 组件对象向也有一个data属性(也可以有methods等属性)
  • 只是这个data属性必须是一个函数
  • 而且这个函数返回一个对象,对象内部保存着数据
代码语言:html复制
<div id="app">
    <cpn1></cpn1>
    <cpn2></cpn2>
</div>

<!-- 1 script标签,注意:类型必须是text/x-template -->
<script type="text/x-template" id="cpn1">
    <div>
        <h2>标题1</h2>
        <p>666</p>
    </div>
</script>

<!-- 2 template标签 -->
<template id="cpn2">
    <div>
        <h2>标题2</h2>
        <p>777</p>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>

  // 注册一个全局组件
  Vue.component('cpn1', {
    template: '#cpn1'
  })
  Vue.component('cpn2', {
    template: '#cpn2'
  })

  const app = new Vue({
    el: '#app',
    data: {
      message: "你好,有勇气的牛排"
    }
  })
</script>

7 组件中data为什么是函数

代码语言:html复制
<div id="app">
    <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn>
</div>

<!-- 组件实例对象 -->
<template id="cpn">
    <div>
        <h2>当前计数:{{ counter }}</h2>
        <button @click="increment"> </button>
        <button @click="decrement">-</button>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
  // 1 注册组件
  Vue.component('cpn', {
    template: '#cpn',
    data() {
      return {
        counter: 0
      }
    },
    methods: {
      increment() {
        this.counter  ;
      },
      decrement() {
        this.counter--;
      }
    }
  })

  const app = new Vue({
    el: '#app',
    data: {
      message: "你好,有勇气的牛排"
    }
  })
</script>

8 父子组件的通信

  • 通过props想自键传递数据
  • 通过时间向父组件发送消息

props数据验证

支持:String、Number、Boolean、Array、Object、Date、Function、Symbol

代码语言:html复制
<div id="app">
    <!--    <cpn v-bind:cmovies="movies" :cmessage="message"></cpn>-->
    <cpn v-bind:cmovies="movies"></cpn>
</div>

<template id="cpn">
    <div>
        <h2>{{ cmessage }}</h2>
        <ul>
            <li v-for="item in cmovies">{{ item }}</li>
        </ul>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
  // 父传子:props
  const cpn = {
    template: '#cpn',
    // props: ['cmovies', 'cmessage'],
    props: {
      // 1 类型限制
      // cmovies:Array,
      // cmessage:String

      // 2 提供一些默认值
      cmessage: {
        type: String,
        default: '666',
        required: true
      },

      // 类型是对象或者数组时,默认值必须是一个函数
      cmoves: {
        type: Array,
        default() {
          return []
        }
      }
    },
    data() {
      return {}
    },
    methods: {}
  }

  const app = new Vue({
    el: '#app',
    data: {
      message: "你好,有勇气的牛排",
      movies: ['三体', '金刚狼', '疯狂外星人']
    },
    components: {
      cpn
    }
  })
</script>

9 父子通信-父传子(props中的驼峰命名)

代码语言:html复制
<div id="app">
    <cpn :c-info="info" :child-my-message="message"></cpn>
</div>

<template id="cpn">
    <h2>{{ cInfo }}</h2>
</template>

<script src="../js/vue.js"></script>
<script>

  const cpn = {
    template: '#cpn',
    props: {
      cInfo: {
        type: Object,
        default() {
          return {}
        }
      },
      childMyMessage: {
        type: String,
        default: ''
      }
    }
  }

  const app = new Vue({
    el: '#app',
    data: {
      info: {
        name: "有勇气的牛排",
        age: 18,
        sex: 0
      }
    },
    components: {
      cpn
    }
  })
</script>

10 组件通信-子传父(自定义事件)

什么时候需要使用自定义事件?

  • 当子组件需要想父组件传递数据时,就要用到自定义事件了
  • v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件

自定义事件的流程

  • 在子组件中,通过$emit()来触发事件。
  • 在父组件中,通过v-on来鉴定子组件事件
代码语言:html复制
<!-- 子组件模板 -->
<template id="cpn">
    <div>
        <button v-for="item in categories"
                @click="btnClick(item)">
            {{ item.name }}
        </button>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>

  // 1 子组件
  const cpn = {
    template: '#cpn',
    data() {
      return {
        categories: [
          {id: '1', name: '热门推荐'},
          {id: '2', name: '手机数码'},
          {id: '3', name: '家电'},
          {id: '4', name: '电脑办公'},
          {id: '5', name: '衣服'},
          {id: '6', name: '玩具'}
        ]
      }
    },
    methods: {
      btnClick(item) {
        // console.log(item)
        // 发射事件: 自定义事件
        this.$emit('item-click', item)
      }
    }
  }

  // 2 父组件
  const app = new Vue({
    el: '#app',
    data: {
      message: '有勇气的牛排'
    },
    components: {
      cpn
    },
    methods: {
      cpnclick(item) {
        console.log('cpnclick', item);
      }
    }
  })
</script>

11 12 组件通信 案例

见gitee源代码

13 父子组件的访问方式:$children

有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是组件访问跟组件。

  • 父组件访问子组件:使用$children或者$refs(reference 引用)
  • 子组件访问父组件:$parent
代码语言:html复制
<div id="app">
    <cpn></cpn>
    <cpn ref="key1"></cpn>
    <cpn></cpn>
    <button @click="btnClick">按钮</button>
</div>

<template id="cpn">
    <div>我是子组件</div>
</template>

<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: "你好,有勇气的牛排"
    },
    methods: {
      btnClick() {
        // 1 $children
        // console.log(this.$children);
        // this.$children[0].showMessage();
        // this.$children[0].name;
        // for(let c of this.$children){
        //   c.showMessage();
        // }

        // 2 $refs => 对象类型,默认是一个空对象 ref='key1'
        console.log(this.$refs.key1.name);

      }
    },
    components: {
      cpn: {
        template: '#cpn',
        data() {
          return {
            name: '我是子组件的name'
          }
        },
        methods: {
          showMessage() {
            console.log('showMessage');
          }
        }
      }
    }
  })
</script>

0 人点赞