Vue组件化开发

1.认识组件化开发

组件化开发思想

组件化思想的特点:标准、分治、复用、组合

 组件: 一个独立封装的带有 html+css+js 的完整内容

如何书写(vue 的规则)

=> 书写一个对象表示一个组件

=> 注意:

-> 每一个组件对象必须要有一个 template 属性, 表示该组件的 html 结构部分

-> 每一个组件可以有一个 name 属性, 表示该组件的内部名称, 是在 Vue 底层遍历组件的时候使用的

-> 每一个组件可以书写的其他配置项(内容) 和 Vue 实例一模一样

-> **每一个组件自己准备的 数据(属性,函数,侦听器,计算属性,...) 只能在自己组件内使用**

书写一个简单的组件对象

const comOne = {
      template: `
        <div>
          <p>我是组件一</p>
          <p>{{ message }}</p>
          <button @click="handler"></button>
          <p v-xhl>{{ msg }}</p>
        </div>
      `,
      data () {
        return {
          message: 'hello comOne'
        }
      },
      methods: {
        handler () {}
      },
      computed: {
        msg () { return this.message.split('').reverse().join('') }
      },
      directives: {
        xhl: {
          mounted (el) { el.style.color = 'red' }
        }
      }
    }

2.组件化开发步骤

+步骤

        1.准备一个组件对象

        2.把组件对象挂到 vue  实例身上开始使用

                   + 步骤

                        1. 准备一个组件对象 

                        2. 把组件对象挂载到 vue 实例身上开始使用

                                2-1. 挂载到全局: 谁都可以使用

                                2-2. 挂载到私有:当前实例或者当期组件才能使用

                =>使用组件:可以在使用的位置直接把组件名称当做标签来使用即可

                    +定义数组的注意

                                => 当你在书写组件使用名称的时候,尽量使用两个及两个以上单词组成

<div id="app">
    <p>组件化开发</p>
    <p>{{ message }}</p>
    -----------------------------
    <gx-xhl></gx-xhl>
    -----------------------------
    <gx-two></gx-two>
  </div>
<script src="./vue.global.js"></script>
<script>
    const { createApp } = Vue
    //准备一个组件对象
    const comOne = {
        template:`
            <div>
                <p>{{message}}</p>
            </div>
        `,
        data () {
            return { message: 'hello comOne'  }
        }
    }   
    const comOne = {
        template:`
            <div>
                <p>{{message}}</p>
            </div>
        `,
        data () {
            return { message: 'hello comOne'  }
        }
    }   
    // 2.把组件对象挂载到 Vue 实例上
    // 2-1. 挂载到全局上
    // 语法:vue 实例.component('组件使用名称',组件对象)
    // 组件使用名称:在 Vue 实例内使用该组件时候的名称
    // app.component('gx-xhl',comOne)

    //2-2. 挂载到一个私有组件
    //直接把组件挂载到 Vue 实例上
    //在 Vue 的实例上身上添加一个 components 配置项,表示该使用实例使用的组件
    const app = crateApp({
        data () {
            return { message: 'hello vue 实例'}
        },
    //    配置组件
    components: {
        // gx-xhl 就是改组件使用名称
        // comOne 就是该组件的真实内容
        'gx-xhl': comOne,
        'gx-two': comTwo
    }
}).mount('#app')
</script>

3.模拟模块化使用组件

index.html

  <div id="app">
    <p>组件化开发</p>
    <p>{{ message }}</p>
    ------------------------------------------
    <xhl-one></xhl-one>
    ------------------------------------------
    <xhl-two></xhl-two>
  </div>

  <script src="../vue.global.js"></script>
  <script type="module">
    import comOne from './comOne.js'
    import comTwo from './comTwo.js'
    const { createApp } = Vue

    createApp({
      data () {
        return {
          message: 'hello Vue 实例'
        }
      },
      components: {
        'xhl-one': comOne,
        'xhl-two': comTwo
      }
    }).mount('#app')
  </script>

comOne.js

import comThree from './comThree.js'

// 我是一号组件
const template = `
  <div>
    <p>{{ message }}</p>
    ********************************
    <xhl-three></xhl-three>
    ********************************
  </div>
`

const component = {
  template,
  data () {
    return {
      message: 'hello comOne'
    }
  },
  components: {
    'xhl-three': comThree
  }
}

// 导出该组件
export default component

comThree.js

// 我是一号组件
const template = `
  <div>
    <p>{{ message }}</p>
  </div>
`
const component = {
  template,
  data () {
    return {
      message: 'hello comThree'
    }
  }
}

// 导出该组件
export default component

comTwo.js

// 我是一号组件
const template = `
  <div>
    <p>{{ message }}</p>
  </div>
`

const component = {
  template,
  data () {
    return {
      message: 'hello comTwo'
    }
  }
}

// 导出该组件
export default component

输出结果

4.组件间通信 

        +分类

              => 父传子:讲父组件的数据给到子组件内

              => 子传父: 将子组件的数据给到父组件内

              => 非父子: 只要不是父子关系都可以

        +方式方法:

                1.父传子:props down(属性下发)

                2.子传父:events up(事件上传)

                3. 非父子:

                        => 发布订阅模式(global event bus - 全局事件总线)

                        => inject / previde

                        => $parent / $children

                        => $refs

                        => vuex - vue 提供的核心插件的一部分(Vue@2 比较多用)

                        => pinia - vue 提供的核心插件的一部分(Vue@3 比较多用)

                        => slot - 插槽

               父传子

                        +将父组件的数据传递给子组件使用

                        + 方法 :props down

                关键点

                     1.组件内的配置项可以书写一个叫做 props的配置项(基础用法,是一个数组)

                        => 读取的是改组件使用时候标签名称上的所有属性

                     2. 组件内的 props 接受的数据可以在组件的 html 结构内使用
                        => 组件被使用的位置是父组件的html结构,可以动态绑定父组件的数据

                    方式:

                        +在组件内以 props 的方法来接受组件标签名上的属性

                        +在组件标签名上动态绑定父组件的数据

                    

                     组件内的 props 属性值

                        => 可以是一个数组, 用到哪一个接受哪一个

                        => 可以是一个对象

                        => 对象内的 key 是你要接受的数据

                        => 对象内的 value 是你对该数据的限制

                        

                     注意: 当你的父组件向子组件传递复杂数据类型的时候, 传递的是数据地址

                        => 在子组件内改变的时候, 会同时改变父组件内的数据

                        => Vue 推荐我们遵循单向数据流

                        => 当你想修改子组件内接受的复杂数据类型的时候, 建议你告诉父组件你想改, 让父组件改变原始数据去

父传子 

<div id="app">
    <p v-bind:s="message">Vue 的生命周期顺序</p>
    <p>{{ message }}</p>
    <button @click="message += '!'">按钮</button>
    <!-- ------------------------ -->
    <!-- <xhl-one :s="message" a="100" b="300"></xhl-one> -->
    <!-- <xhl-one s="我是 Vue 实例内定义的 message 数据" a="100" b="300"></xhl-one> -->
    <!-- <xhl-one b="500"></xhl-one> -->
    <!-- ------------------------
    <xhl-two :n="num" :m="num"></xhl-two>
    <xhl-two :n="num" :z="num"></xhl-two>
    <xhl-two :n="num"></xhl-two> -->
    ------------------------
    <xhl-three :n="num" :s="message"></xhl-three>
  </div>

  <script src="./vue.global.js"></script>
  <script>
     const comOne = {
      template: `
        <div>
          one 组件 - 在这里使用到 Vue 实例内定义的 message 变量的数据
          <p>{{ a }} --- {{ b }} --- {{ s }}</p>
        </div>
      `,
      data () {
        return {}
      },
      methods: {},
      props: [ 'a', 'b', 's' ]
    }

    const comTwo = {
      template: `
        <div>two 组件 </div>
        <p>n : {{ n }}</p>
        <p>m : {{ m }}</p>
        <p>z : {{ z }}</p>
      `,
      props: {
        n: {
          required: true,
          type: Number
        },
        m: {
          type: Number,
          default: 0
        },
        z: {
          type: Number,
          default (param) {
            return 999
          }
        }
      }
    }

    const comThree = {
      template: `
        <div>
          three 组件
          <p>n : {{ n }}</p>
          <p>s : {{ s }}</p>
        </div>

      `,
      props: [ 'n', 's' ]
    }

    const { createApp } = Vue

    createApp({
      data () {
        return {
          message: '我是 Vue 实例内定义的 message 数据',
          num: 100
        }
      },
      components: {
        'xhl-one': comOne,
        'xhl-two': comTwo,
        'xhl-three': comThree,
      }
    }).mount('#app')

  </script>

   子传父

 <div id="app">
    <p>Vue 的生命周期顺序</p>
    <p>{{ str }}</p>

    <!--
      当该 div 发生了 click 行为, 会触发 handler 函数
      handler 函数, 是 Vue 实例内准备的函数
    -->
    <!-- <div @click="handler"></div> -->


    <!--
      当该 div 发生了 abcd 行为, 会触发 handler 函数
    -->
    <!-- <div @abcd="handler"></div> -->

    <!--
      当该 xhl-aaa 组件发生了 abcd 行为, 会触发 handler 函数
    -->
    <!-- <xhl-aaa @abcd="hanlder"></xhl-aaa> -->

    <p>购买数量 : {{ num }}</p>
    <p>总价 : {{ num * 100 }}</p>

    ------------------------
    <xhl-one @update="handler"></xhl-one>
    ------------------------
    <!-- 当 two 组件发生 add 行为的时候, 触发 addHandler 函数 -->
    <!-- 让自己的 num 修改 -->
    <xhl-two @add="addHandler" @add2="addHandler2"></xhl-two>
  </div>

  <script src="./vue.global.js"></script>
  <script>
    /*
      子传父
        + 考虑时间点:
          => 假设: 我们在打开页面, 初始渲染组件的时候, 就需要把子组件的数据传递给父组件
            -> 不会出现的情况, 如果这样的话, 我们可以直接把数据书写在父组件内
          => 一定: 在某些 "行为" 发生的时候, 传递给父组件一些数据进行使用
        + 例子: 购物车(表格类的内容)
          => 当你点击某一个组件内的数量减少的时候
          => 通知父组件
          => 当你点击某一个组件内的选项的时候

      传递方式 : events up (事件上传)
        + 依赖一个事件行为
        + 在父组件内 :
          => 当你使用子组件标签的时候, 给添加一个自定义事件, 绑定事件处理函数
          => 在子组件内, 当你需要传递数据的时候, 使用 this.$emit('事件类型') 去触发自定义事件行为

      总结:
        + 父传子
          => 在父组件内, 当你使用子组件标签的时候, 把要传递的数据绑定在标签上
          => 在子组件内, 用 props 属性接受
        + 子传父
          => 在父组件内, 当你使用子组件标签的时候, 通过自定义事件的方式, 绑定一个事件处理函数
          => 在子组件内, 当你需要传递数据的时候, 使用 this.$emit() 来触发自定义事件行为
    */

    const comOne = {
      template: `
        <div>
          one 组件 - 在这里使用到 Vue 实例内定义的 message 变量的数据
          <button @click="oneHandler">我需要把我的数据传递给父组件</button>
        </div>
      `,
      data () {
        return {
          message: '我是子组件内准备的数据'
        }
      },
      methods: {
        oneHandler () {
          console.log('点击了 one 组件内的 button 按钮')
          // 让当前组件触发一个 update 行为
          // 语法: this.$emit('事件类型', 携带参数)

          // 这句代码一旦执行, 就会让当前组件触发一个 update 行为
          // this => 当前组件
          // $emit => 触发行为
          this.$emit('update', this.message)
          // 当你点击组件内的 button 按钮的时候, 让当前组件触发了一个 update 行为
          // 因为组件内的 update 行为发生了, 会触发父组件内绑定 update 相关的事件处理函数
          // 就执行了父组件内的 methods 内准备的 handler 函数
        }
      }
    }

    // 需求: 点击组件内的 购买数量+ 按钮的时候, 修改父组件内的数据
    const comTwo = {
      template: `
        <div>
          我是购物车内的某一项
          <button @click="handler">+</button>
          <br>
          <input type="text" v-model="n" />
          <button @click="handler2">确认</button>
        </div>
      `,
      data () {
        return {
          n: 0
        }
      },
      methods: {
        handler () {
          // 点击 购买数量+ 按钮了
          // 应该让当前组件触发 add 行为
          this.$emit('add')
        },
        handler2 () {
          this.$emit('add2', this.n)
        }
      }
    }

    const { createApp } = Vue

    createApp({
      data () {
        return {
          str: '',
          num: 3
        }
      },
      methods: {
        handler (s) {
          console.group('父组件的 handler 函数')
          console.log('xhl-one 组件发生了 update 行为')
          console.log(s)
          this.str = s
          console.groupEnd()
        },
        addHandler () {
          this.num++
        },
        addHandler2 (n) {
          console.log('我要增加 ' + n + ' 个')
          this.num += n - 0
        }
      },
      components: {
        'xhl-one': comOne,
        'xhl-two': comTwo
      }
    }).mount('#app')
  </script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值