Vue組件化開(kāi)發(fā)

上期回顧

  • 條件判斷(v-if、v-show)的基本使用、開(kāi)發(fā)時(shí)選擇
  • 條件渲染案例(input添加key的區(qū)別)
  • 循環(huán)遍歷(v-for)
  • 表單綁定(v-model)
  • lazy修飾符
  • number修飾符
  • trim修飾符
  • 拓展:數(shù)組的響應(yīng)式方法

什么是組件化:

獨(dú)立的,可復(fù)用的,整體化的一個(gè)功能模塊

為什么要組件化:

1.實(shí)現(xiàn)功能模塊的復(fù)用
2.開(kāi)發(fā)單頁(yè)面復(fù)雜應(yīng)用
3.高效執(zhí)行


組件化開(kāi)發(fā)

注冊(cè)組件

三大步驟
1.創(chuàng)建組件構(gòu)造器( Vue.extend() )
2.注冊(cè)組件( Vue.component() )
3.使用組件

  • 代碼演練
  <div id="app">
    <!-- 第三步:使用組件 -->
    <my-cpn></my-cpn>
    <!-- 錯(cuò)誤的使用方式 -->
    <myCpn></myCpn>
  </div>

  <script src="../js/vue.js"></script>
  <script>
    //第一步:創(chuàng)建組件構(gòu)造器
    let cpn = Vue.extend({
      template: `
      <div>
        <h2>我是組件</h2>
      </div>
      `
    })

    //第二步:注冊(cè)組件
    Vue.component("myCpn", cpn)

    const app = new Vue({
      el: "#app",
      data: {

      }
    })
  </script>
組件的使用

注意:
第三步不能使用小駝峰命名,大寫(xiě)字母變?yōu)樾?xiě)字母,前面加 "-"

Vue.extend({template})
Vue.extend():返回一個(gè)組件構(gòu)造器
template:代表自定義組件的html模板
Vue.vomponent("組件命名",組件構(gòu)造器)
Vue.vomponent():注冊(cè)組件


全局組件和局部組件

  • 代碼演示
  <div id="app1">
    <!-- 全局 -->
    <global-cpn></global-cpn>
    <!-- 局部 -->
    <part-cpn></part-cpn>
  </div>
  <div id="app2">
    <!-- 全局 -->
    <global-cpn></global-cpn>
    <!-- 局部 -->
    <part-cpn></part-cpn>
  </div>

  <script src="./js/vue.js"></script>
  <script>
    //1.創(chuàng)建全局組件構(gòu)造器
    let cpn1 = Vue.extend({
      template: `
          <div>
            <h2>我是全局組件</h2>  
          </div>
        `
    })
    //1.創(chuàng)建局部組件構(gòu)造器
    let cpn2 = Vue.extend({
      template: `
          <div>
            <h2>我是局部組件</h2>  
          </div>
        `
    })

    //2.注冊(cè)全局組件
    Vue.component("globalCpn", cpn1)
    const app1 = new Vue({
      el: "#app1",
      //第二步:注冊(cè)局部組件
      components: {
        "partCpn": cpn2
      }
    })
    const app2 = new Vue({
      el: "#app2"
    })
  </script>
全局組件和局部組件

父組件和子組件

  • 代碼演示
  <div id="app">
    <!-- 使用父組件 -->
    <father-cpn></father-cpn>
  </div>

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

    //1.創(chuàng)建子組件構(gòu)造器
    let cpn2 = Vue.extend({
      template: `
          <div>
            <h2>我是子組件</h2>  
          </div>
        `
    })

    //1.創(chuàng)建父組件構(gòu)造器
    let cpn1 = Vue.extend({
      template: `
          <div>
            <h2>我是父組件</h2>
            <!-- 使用子組件 -->
            <son-cpn></son-cpn>
          </div>
        `,
      //在父組件中掛載子組件
      components: {
        "sonCpn": cpn2
      }
    })

    const app1 = new Vue({
      el: "#app",
      //在全局組件中掛載父組件
      components: {
        "fatherCpn": cpn1
      }
    })
  </script>
父組件和子組件

組件的簡(jiǎn)寫(xiě)方式

  • 代碼演示
  <div id="app">
    <!-- 使用全局組件 -->
    <global-cpn></global-cpn>
    <!-- 使用局部組件 -->
    <part-cpn></part-cpn>

  </div>

  <script src="./js/vue.js"></script>
  <script>
    // 創(chuàng)建全局組件
    Vue.component("globalCpn", {
      template: `
        <div>
          <h2>我是全局組件</h2>
        </div>
      `
    })

    const app1 = new Vue({
      el: "#app",
      // 創(chuàng)建局部組件
      components: {
        "partCpn": {
          template: `
            <div>
              <h2>我是局部組件</h2>
            </div>
          `
        }
      }
    })
  </script>
組件簡(jiǎn)寫(xiě)

省去了Vue.extend()的步驟,直接用一個(gè)對(duì)象代替


模板的兩種分離寫(xiě)法

1.使用<script>標(biāo)簽

  • 代碼演示
  <div id="app">
    <my-cpn></my-cpn>
  </div>
  <!-- 使用<script>標(biāo)簽,注意加上type屬性和id屬性 -->
  <script type="text/x-template" id="myCpn">
    <div>
      <h2>我是組件</h2>
    </div>
  </script>
  <script src="./js/vue.js"></script>
  <script>
    const app1 = new Vue({
      el: "#app",
      // 創(chuàng)建局部組件
      components: {
        "myCpn": {
          template: "#myCpn"
        }
      }
    })
  </script>
使用<script>標(biāo)簽

2.使用<template>標(biāo)簽(推薦)

  • 代碼演示
  <div id="app">
    <my-cpn></my-cpn>
  </div>
  <!-- 使用<template>標(biāo)簽,注意加上id屬性 -->
  <template id="myCpn">
    <div>
      <h2>我是組件</h2>
    </div>
  </template>
  <script src="./js/vue.js"></script>
  <script>
    const app1 = new Vue({
      el: "#app",
      // 創(chuàng)建局部組件
      components: {
        "myCpn": {
          template: "#myCpn"
        }
      }
    })
  </script>
使用<template>標(biāo)簽(推薦)

注意:
使用兩種標(biāo)簽,主要是將template中的html模板抽離出去,所以,兩種標(biāo)簽一定要加上id屬性,用于template的綁定


組件數(shù)據(jù)的處理

  • 代碼演示
  <div id="app">
    {{message1}} - {{message2}}
    <my-cpn></my-cpn>
  </div>
  <template id="myCpn">
    <div>
      <h2>{{message1}}</h2>
      <h2>{{message2}}</h2>
    </div>
  </template>
  <script src="./js/vue.js"></script>
  <script>
    cpn = {
      "myCpn": {
        template: "#myCpn",
        // 數(shù)據(jù)存放在組件內(nèi)部,組件可以訪問(wèn),全局不能
        data() {
          return {
            message2: "組件內(nèi)的數(shù)據(jù)"
          }
        },
      }
    }

    const app1 = new Vue({
      el: "#app",
      components: cpn,
      // 數(shù)據(jù)存放在實(shí)例的data內(nèi),全局可以訪問(wèn)在組件中無(wú)法訪問(wèn)
      data() {
        return {
          message1: "實(shí)例內(nèi)的數(shù)據(jù)"
        }
      },
    })
  </script>
組件數(shù)據(jù)的處理
注意:

組件中data必須是函數(shù):這樣可以保證組件每次使用的數(shù)據(jù)不會(huì)被別的組件更改,保證各組件間的數(shù)據(jù)互不干擾,data不是函數(shù)時(shí),會(huì)報(bào)錯(cuò)?。?!


組件間的數(shù)據(jù)傳遞(父?jìng)髯樱?/h4>

props基本用法
  • 代碼演示
  <div id="app">
    <!-- 1.通過(guò)v-bind綁定數(shù)據(jù)message -->
    <my-cpn :info="message"></my-cpn>
  </div>
  <template id="myCpn">
    <div>
      <!-- 3.展示組件內(nèi)props的數(shù)據(jù) info -->
      <h2>{{info}}</h2>
    </div>
  </template>
  <script src="./js/vue.js"></script>
  <script>
    cpn = {
      "myCpn": {
        template: "#myCpn",
        // 2.接收組件標(biāo)簽綁定的數(shù)據(jù)
        props: ["info"]
      }
    }

    const app1 = new Vue({
      el: "#app",
      components: cpn,
      data: {
        message: "hello Vue"
      }
    })
  </script>
props基本用法

注意數(shù)據(jù)傳遞過(guò)程:
1.通過(guò)v-bind綁定數(shù)據(jù)messag
2.接收組件標(biāo)簽綁定的數(shù)據(jù)
3.展示組件內(nèi)props的數(shù)據(jù) info

props數(shù)據(jù)驗(yàn)證
  • 代碼演示
  <div id="app">
    <my-cpn :info="message" :addNum="add()" :num="num3"></my-cpn>
  </div>

  <template id="myCpn">
    <div>
      <h2>{{info}}</h2>
      <h2>{{addNum}}</h2>
      <h2>{{num}}</h2>
      <h2>{{str}}</h2>
    </div>
  </template>

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

    const app = new Vue({
      el: "#app",
      data: {
        message: "hello Vue",
        num1: 3,
        num2: 5,
        num3: 10,
        str: "test"
      },
      methods: {
        add() {
          console.log(this.num1 + this.num2)
        }
      },
      components: {
        "my-cpn": {
          template: "#myCpn",
          props: {
            // key:類(lèi)型
            info: String,
            addNum: Function,
            num: {
              type: Number,
              // 設(shè)為必填值
              required: true,
            },
            str: {
              type: String,
              // 設(shè)置默認(rèn)值
              default: "我是默認(rèn)值"
            }
          }
        }
      }
    })
  </script>
props數(shù)據(jù)驗(yàn)證
  • props支持驗(yàn)證類(lèi)型
    String
    Number
    Array
    Boolean
    Function
    Object
    Date
    Symbol

組件間的數(shù)據(jù)傳遞(子傳父)

  • 代碼演示
  <div id="app">
    <h2>{{num}}</h2>
    <!-- 第四步:  將子組件傳出的函數(shù)轉(zhuǎn)為自定義函數(shù),并綁定自定義事件的實(shí)現(xiàn)函數(shù)-->
    <son-cpn :amount="num" @add="change" @cut="change"></son-cpn>
  </div>

  <template id="myCpn">
    <div>
      <!-- 第一步: 綁定事件 -->
      <button @click="add">加10</button>
      <button @click="cut">減10</button>
    </div>
  </template>

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

    const app = new Vue({
      el: "#app",
      data: {
        num: 1
      },
      methods: {
        // 第五步: 實(shí)現(xiàn)自定義事件的函數(shù)
        // count 是第三步傳入的參數(shù)
        change(count) {
          this.num = count
        }
      },
      components: {
        "sonCpn": {
          template: "#myCpn",
          props: {
            amount: {
              type: Number,
              required: true,
            }
          },
          data() {
            return {
              count: this.amount
            }
          },
          methods: {
            // 第二步: 事件函數(shù)的實(shí)現(xiàn)
            add() {
              this.count += 10
              // this.amount += 10  避免直接改變屬性,因?yàn)楫?dāng)父組件重新呈現(xiàn)時(shí),該值將被覆蓋。

              // 第三步: 使用 emit("函數(shù)名",參數(shù)) 通知父組件,并傳遞參數(shù)
              this.$emit("add", this.count)
            },
            cut() {
              this.count -= 10
              // this.amount += 10 避免直接改變屬性,因?yàn)楫?dāng)父組件重新呈現(xiàn)時(shí),該值將被覆蓋。
              
              // 第三步: 使用 emit("函數(shù)名",參數(shù)) 通知父組件,并傳遞參數(shù)
              this.$emit("cut", this.count)
            }
          }
        }
      }
    })
組件間的數(shù)據(jù)傳遞(子傳父)

注意一

注意二

數(shù)據(jù)傳遞(子傳父)過(guò)程
1.在子組件中,通過(guò)$emit("事件名",參數(shù))來(lái)觸發(fā)事件。
2.在父組件中,通過(guò)v-on來(lái)監(jiān)聽(tīng)子組件事件。

父組件直接訪問(wèn)子組件的數(shù)據(jù)($children、$refs)

  • 代碼演示
  <div id="app">
    <f-cpn></f-cpn>
  </div>

  <!-- 子組件模板 -->
  <template id="zCpn">
    <div>
      <h2>我是子組件</h2>
      <h2>{{info}}</h2>
      <h2>調(diào)用方法:{{mult}}</h2>
    </div>
  </template>

  <!-- 父組件模板 -->
  <template id="fCpn">
    <div>
      <h2>我是父組件</h2>
      <!-- 通過(guò)ref給某一個(gè)子組件綁定一個(gè)特定的ID -->
      <z-cpn ref="child"></z-cpn>
      <button @click="access$children">通過(guò)$children訪問(wèn)子組件</button>
      <button @click="access$refs">通過(guò)$refs訪問(wèn)子組件</button>
    </div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    //子組件實(shí)例
    let zCpn = {
      template: "#zCpn",
      data() {
        return {
          info: "我是子組件數(shù)據(jù)",
          num: 2
        }
      },
      computed: {
        mult() {
          return this.num * 3
        }
      }
    }

    const app = new Vue({
      el: "#app",
      data: {
      },
      components: {
        // 注冊(cè)父組件
        "f-cpn": {
          template: "#fCpn",
          components: {
            // 注冊(cè)子組件
            "z-cpn": zCpn
          },
          methods: {
            access$children() {
              // 通過(guò)$children訪問(wèn)子組件
              console.log(this.$children)
              console.log(this.$children[0].info)
              console.log(this.$children[0].mult)
              // console.log(this.$children[0].mult())    ?錯(cuò)誤寫(xiě)法,mult是計(jì)算屬性,不是函數(shù)
            },
            access$refs(){
              // 通過(guò)$refs訪問(wèn)子組件
              console.log(this.$refs)
              console.log(this.$refs.child)
              console.log(this.$refs.child.info)
              console.log(this.$refs.child.mult)
              // console.log(this.$refs.child.mult())       ?錯(cuò)誤寫(xiě)法,mult是計(jì)算屬性,不是函數(shù)
            }
          }
        }
      }
    })
  </script>
$children的使用

$refs的使用

總結(jié):

  • $children需要通過(guò)子組件的下標(biāo)($children[index]),才能訪問(wèn)該子組件,易出錯(cuò),
  • $refs是通過(guò)ref綁定的ID訪問(wèn)子組件($refs.ID),更加精確到位,推薦使用$refs

子組件直接訪問(wèn)父組件的數(shù)據(jù)($parent)

  • 代碼演示
  <div id="app">
    <f-cpn></f-cpn>
  </div>

  <!-- 子組件模板 -->
  <template id="zCpn">
    <div>
      <h2>我是子組件</h2>
      <button @click="getFInfo">點(diǎn)擊獲取父組件的信息</button>
    </div>
  </template>

  <!-- 父組件模板 -->
  <template id="fCpn">
    <div>
      <h2>我是父組件</h2>
      <z-cpn></z-cpn>
    </div>
  </template>

  <script src="../js/vue.js"></script>
  <script>
    //子組件實(shí)例
    let zCpn = {
      template: "#zCpn",
      methods: {
        getFInfo() {
          console.log(this.$parent)
          console.log(this.$parent.info)
          this.$parent.show()
        }
      }
    }

    const app = new Vue({
      el: "#app",
      data: {
      },
      components: {
        // 注冊(cè)父組件
        "f-cpn": {
          template: "#fCpn",
          components: {
            // 注冊(cè)子組件
            "z-cpn": zCpn
          },
          data() {
            return {
              info: "我是父組件信息"
            }
          },
          methods: {
            show(){
              console.log("通過(guò)$parent訪問(wèn)父組件的方法")
            }
          }
        }
      }
    })
  </script>
$parent的使用

注意:
在開(kāi)發(fā)中盡量避免子組件通過(guò)$parent直接訪問(wèn)父組件的數(shù)據(jù),因?yàn)檫@樣耦合度太高了。而且這樣會(huì)使父組件中的狀態(tài)將變得飄忽不定,很不利于我的調(diào)試和維護(hù)。

插槽(slot)的使用

插值基本用法
  • 代碼演示
  <div id="app">
    <div>==========單個(gè)slot使用==========</div>
    <my-cpn1></my-cpn1>
    <my-cpn1>
      <!-- 填入內(nèi)容替換插槽 -->
      <h2>hello vue</h2>
    </my-cpn1>
    <div>==========具名solt使用==========</div>
    <!-- 如果my-cpn2內(nèi)部沒(méi)有內(nèi)容,具名插槽不會(huì)顯示,不具名插槽會(huì)顯示,如my-cpn1 -->
    <my-cpn2></my-cpn2>
    <!-- 如果my-cpn2內(nèi)部所有的標(biāo)簽都綁定了具名插槽,則不具名的插槽不會(huì)顯示 -->
    <my-cpn2>
      <div name="content1"><h2>替換文字1</h2></div>
      <div name="content2"><h2>替換文字2</h2></div>
      <div name="content3"><h2>替換文字3</h2></div>
    </my-cpn2>
  </div>
  <template id="mySlot1">
    <div>
      <!-- 設(shè)置一個(gè)插槽 -->
      <slot>默認(rèn)內(nèi)容</slot>
    </div>
  </template>
  <template id="mySlot2">
    <div>
      <!-- 設(shè)置一個(gè)插槽 -->
      <slot><h2>默認(rèn)內(nèi)容3</h2></slot>
      <!-- 設(shè)置三個(gè)具名插槽 -->
      <slot slot="content1"><h2>默認(rèn)內(nèi)容1</h2></slot>
      <slot slot="content2"><h2>默認(rèn)內(nèi)容2</h2></slot>
      <slot slot="content3"><h2>默認(rèn)內(nèi)容3</h2></slot>
    </div>
  </template>
  <script src="../js/vue.js"></script>
  <script>

    const app = new Vue({
      el: "#app",
      components: {
        myCpn1: {
          template: "#mySlot1"
        },
        myCpn2: {
          template: "#mySlot2"
        }
      }
    })
  </script>
插槽(slot)的使用
slot數(shù)據(jù)傳遞
  • 代碼演示
  <div id="app">
    <my-cpn>
      <!-- 第二步: 接收數(shù)據(jù) -->
      <template slot-scope="props">
        <ul>
          <!-- 第三步: 使用數(shù)據(jù) -->
          <li v-for="(value,index) in props.info">{{index}} - {{value}}</li>
        </ul>
      </template>
    </my-cpn>
  </div>
  <template id="mySlot">
    <div>
      <!-- 第一步: 綁定數(shù)據(jù) -->
      <slot :info="course"></slot>
    </div>
  </template>
  <script src="../js/vue.js"></script>
  <script>

    const cpn = {
      template: "#mySlot",
      data() {
        return {
          course: {
            1001: "Python入門(mén)",
            1002: "數(shù)據(jù)結(jié)構(gòu)與算法",
            1003: "離散數(shù)學(xué)",
            1004: "概率論",
            1005: "形式與政策",
          }
        }
      }
    }

    const app = new Vue({
      el: "#app",
      components: {
        myCpn: cpn
      }
    })
  </script>
slot數(shù)據(jù)傳遞

注意:

注意

編譯作用域(補(bǔ)充)

  • 代碼演示
  <div id="app">
    <my-cpn v-if="isShow">
    </my-cpn>
  </div>
  <template id="mySlot">
    <div>
      <slot>默認(rèn)數(shù)據(jù)</slot>
    </div>
  </template>
  <script src="../js/vue.js"></script>
  <script>

    const cpn = {
      template: "#mySlot",
      data() {
        return {
          isShow: false
        }
      }
    }

    const app = new Vue({
      el: "#app",
      components: {
        myCpn: cpn
      },
      data: {
        isShow: true
      }
    })
  </script>
編譯作用域一

編譯作用域二

注意:任意組件模板的所有東西都會(huì)在該模板作用域內(nèi)編譯,即變量會(huì)從該實(shí)例中尋找

END
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 組件化開(kāi)發(fā)步驟:1.創(chuàng)建組件構(gòu)造器 Vue.extend({})2.注冊(cè)組件 Vue.component()3.使...
    似朝朝我心閱讀 462評(píng)論 0 7
  • 一、什么是組件化開(kāi)發(fā) 人面對(duì)復(fù)雜問(wèn)題的處理方式:任何一個(gè)人處理信息的邏輯能力都是有限的所以,當(dāng)面對(duì)一個(gè)非常復(fù)雜的問(wèn)...
    c_gentle閱讀 2,285評(píng)論 0 1
  • 認(rèn)識(shí)組件化 如果我們將一個(gè)頁(yè)面中所有的處理邏輯全部放在一起,處理起來(lái)就會(huì)變得非常復(fù)雜,而且不利于后續(xù)的管理以及擴(kuò)展...
    獨(dú)調(diào)1997閱讀 836評(píng)論 0 0
  • 組件化開(kāi)發(fā)思想 現(xiàn)實(shí)中的組件化思想體現(xiàn)(1)標(biāo)準(zhǔn)(2)分治(3)重用(4)組合 編程中的組件化思想體現(xiàn) 組件化規(guī)范...
    遼A丶孫悟空閱讀 2,030評(píng)論 1 21
  • 組件其實(shí)就是一個(gè)擁有樣式、動(dòng)畫(huà)、js邏輯、HTML結(jié)構(gòu)的綜合塊。前端組件化確實(shí)讓大的前端團(tuán)隊(duì)更高效的開(kāi)發(fā)前端項(xiàng)目。...
    IT老馬閱讀 872評(píng)論 0 1

友情鏈接更多精彩內(nèi)容