# Vue作品實戰班 --- tags: Vue 實戰班 --- ## 主課程 ### 元件建立 - 為什麼需要元件? 1. 避免單一個檔案過大 2. 很多地方會用到的部分可以拉出來做重複使用,方便管理 3. 元件的大小可依據範疇分類 views(整頁)/components(單一小區塊) - 定義方式有什麼? ![](https://i.imgur.com/JBKw9s8.png) 1. 全域元件 在整個Vue內其他元件都可以使用。可重複使用。 ```javascript= Vue.component('元件名稱',{ template: `html內容` }) ``` ```html= <div id='元件名稱'></div> ``` 2. 區域元件 - 在任何元件下 - 在 #app 下也可以 - 只有當前註冊元件內才可以使用 ```javascript= var app = new Vue({ components: { 元件名稱:{ template: `html內容`, } } }) ``` - 元件模板應用方式 1. Template Literial ```javascript= template: `html內容` ``` 2.🌟 x-template ```html= <script type="text/x-template" id="元件模板id"> html內容 </script> ``` - template: 中的程式碼可以拉出來,用 id 綁定,優點:可以把 html 結構拉出來 ![](https://i.imgur.com/SYAFAL5.png) ![](https://i.imgur.com/RPREyK3.png) ```javascript= Vue.component('元件名稱',{ template: '#元件模板id' }) ``` ```javascript= //完整範例 //HTML <card></card> <div is="card"></div> //下一行的寫法,意思同上一行,但兩個 data 是獨立的 //javascript <script type="text/x-template" id="forCard"> <div class="card" style="width: 18rem;"> <div class="card-body"> <h5 class="card-title">{{ text }}</h5> </div> </div> </script> Vue.component('card',{ template: '#forCard' }) ``` 3. vue file 共通重點: > 元件下的模板最外層不可以有兩個節點(html element tag) > - 元件內 data 必須**使用 function 去傳送** ```javascript= Vue.component('card',{ template: '#forCard', //✨內層所有的 data 都必須使用 function return data: function(){ return{ text: '這裡有一句話', } } //以下為縮寫 data(){ return{ text: '這裡有一句話', } } }) ``` - import 的方式 ```javascript= //開一個 card.js 檔,寫入 export default{ template: '#forCard', data: function(){ return{ text: '這裡有一句話', } } } //然後回 html 下的 script 區塊 import card2 from './card.js'; // body 內寫如下即可 <card2></card2> ``` - 呼叫 component 的2種方式 ```javascript= // 自定義標籤 <card></card> // html 標籤 <div is="card"></div> ``` - 元件重點 - template - data - 雷點 ```javascript= //不能在外層暴露結構,也就是必須要有 div 包著 h5,否則會報錯 <script type="text/x-template" id="forCard"> <div> <h5 class="card-title">{{ text }}</h5> <h5 class="card-title">{{ text2 }}</h5> </div> </script> ``` - script type="module" > ES module 可以匯入外部檔案。參考第二週的影片 ### 🛠 學習方法 - 看過一次 - 動手做一次,並且寫成筆記 - 分享給其他人 ### 元件資料傳遞 #### props是什麼? - props是以資料形式,將資料由外層元件往內層元件傳遞 - 如果由內層元件到外層元件的資料傳遞,是以事件的形式傳遞資料($emit事件) - 如果是同一層級的元件對元件,也是以事件的形式傳遞資料(\$on+$emit) ![](https://i.imgur.com/GyDeLkE.png) ```html= <div id='app'> <!--前面是名稱 後面是值--> <card outer='123'></card> </div> ``` ![](https://i.imgur.com/xfMFaQt.png =500x) ![](https://i.imgur.com/Jkudnb6.png =500x) - 把 outer 傳進來,再賦予到 src 上面 ![](https://i.imgur.com/aw6BPYo.png =500x) - 把外部 img 傳到 outer 上的綁定方法,`:outer="img"` ![](https://i.imgur.com/JL83MNN.png) - props有什麼限制? 1.一旦傳入內層元件,內層元件不可以更改它的值(單向數據流) - 如果必須使用props的值,又需要更改,可以透過 created 存到 data 變數內 ![](https://i.imgur.com/NiSBk1m.png) 2. ~~首字一定要小寫,用大寫沒有用;但可以使用小寫駝峰命名法~~ 查詢錄播 [第四週直播 - 下錄播14:57左右](https://courses.hexschool.com/courses/924133/lectures/22412010) 根據Vue官方文件的說明,如果不是使用Template Literial的方式撰寫Template時,props在html的attr上必須依循其不區分大小寫的限制(全部都會被當成小寫),不可使用camel-case(小寫駝峰)。 如果希望js環境內接值時,可以使用camel-case來接收,則html上的props attr必須使用kebab-case,如以下範例: ```html= <mycomponent :product-list="something"></mycomponent> ``` ```javascript= Vue.component('mycomponent', { template: '#mycomponentTemplate', props: ['productList'], data() { return {} }, created() { console.log(this.productList) // something }, }) ``` ![](https://i.imgur.com/dMrTad5.png =400x) ![](https://i.imgur.com/YrDSSXk.png =400x) ![](https://i.imgur.com/iKv5STO.png =400x) [Ref. Vue.js Prop章節](https://cn.vuejs.org/v2/guide/components-props.html) 或是參考 [vue 官方 style guide](https://vuejs.org/v2/style-guide/#Prop-name-casing-strongly-recommended) --- ![](https://i.imgur.com/J4ec9Bz.png) - $emit事件是什麼? ![](https://i.imgur.com/ReVYf7c.png =500x) 外到內是資料。內到外是事件 \$emit是以事件形式將資料由內層元件往外層元件推送傳遞。 內層元件使用$emit推到外層元件由事件接收 ```javascript= // 外層元件 // emit 推,外 methods 接收 // 心法口訣: 前內(emit),後外(method) <card @pushsomething='getData'></card> // 內層元件 methods:{ update(){ this.$emit('pushsomething', this.text) } } ``` **內層** ![](https://i.imgur.com/lt1WGSZ.png =500x) **外層** ![](https://i.imgur.com/jS4YdMX.png =500x) 需要注意的是,不同於元件和 props,$emit 不存在任何大小寫轉換,所以觸發的事件名稱,需要完全符合監聽這個事件所用的名稱。舉個例子,如果想觸發一個 camelCase (小駝峰) 名字的事件: ```javascript= methods: { update() { this.$emit('myEvent') // html 'E'會視為'e'讓 JS 讀不到, 可改用 myevent、my-event or my_event } } ``` 則監聽這個名字的 kebab-case 版本是不會有任何效果的 ```html= <!-- 没有效果 無效! --> <card @my-event="doSomething"></card> ``` 不像元件和 props,事件名稱不會被用來當作一個 JS 的變數或 property 名稱,所以不需要使用駝峰式命名 [Ref. Vue.js $emit/自訂事件](https://cn.vuejs.org/v2/guide/components-custom-events.html) - eventbus是什麼? 1. eventbus 是跨元件傳遞。 ![](https://i.imgur.com/xcTpTCC.png) 2. 利用bus的實體,以事件對事件的形式(完全不需要html屬性,只需要在\$emit和$on使用相同事件名稱即可),在同層級的元件傳遞資料 ```javascript= // 在外層先新增一個Vue實體 Vue.prototype.$bus = new Vue(); // card 1 (推資料) Vue.component('card1',{ template:`<div @click='updateData'>{{text}}</div>`, data(){ return { text: 'card1的資料' } }, method(){ updateData(){ this.$bus.$emit('updateCard2', this.text) } } }) // card 2 (收資料) Vue.component('card2',{ template:`<div>{{anotherData}}</div>`, data(){ return { anotherData: '還未修改的資料' } }, created(){ // 接收 this.$bus.$on('updateCard2',function(para){ console.log('接收到的事件', para); }) //如果想變更 this.anotherData 可以將函式改為箭頭函式 this.$bus.$on('updateCard2', para => { console.log('接收到的事件', para) this.anotherData = para }) //updateCard2 為自訂名稱 //$bus 的缺點:很難除錯 } }) ``` 由於eventbus使用相同名稱的事件名稱來傳遞,如果是在畫面上會重複出現的元件,就不建議使用這個方式做資料傳遞(有同樣接收器,無法區分是要傳遞給哪一個元件的資料),容易出錯。 使用時機:適合一對一的元件 ### 元件生命週期 - 生命週期是什麼? - 元件從建立到移除的過程。 - 如果想維持住生命週期,不希望元件重新循環生命週期,可使用`<keep-alive>`標籤包住 - 搭配 v-if 的問題 `<keep-alive>` - 只有 v-if, v-for 才會觸發生命週期的事件, v-show 不會,v-show 是使用 display: none - jQuery 為什麼會抓不到元素,mounted 後才抓得到元素 - 哪個重要: 1. created - 資料建立之後 - 適合處理資料 2. mounted - 元件渲染出html之後 - 適合處理 DOM ### 主線任務相關 1. 這禮拜一定要看影片才能順利做任務 2. 任務的登入驗證不用給帳號密碼 ### 遇到困難的話... #### 如果有以下情況 1. 看範例作品都會寫,蓋起來就不會 2. 老師直播時都懂,但要自己運用就卡卡的 3. 寫完作業好像失憶一般,再寫一次也不一定有把握 #### 請練習以下兩種方式 1. 寫自己的筆記 寫一次撰寫程式時,搭配筆記做紀錄 第二次撰寫的時候,只能看筆記 2. 練習拆解٩(ˊωˋ*)و✧ ### 自閉合组件 - [HTML 并不支持自闭合的自定义元素](https://cn.vuejs.org/v2/style-guide/#%E8%87%AA%E9%97%AD%E5%90%88%E7%BB%84%E4%BB%B6%E5%BC%BA%E7%83%88%E6%8E%A8%E8%8D%90)