---
# System prepended metadata

title: Vue2
tags: [問題集, Vue2, 前端(frontend), 框架]

---


Vue2
===
###### tags:`前端(frontend)`,`框架`,`Vue2`,`問題集`
# 生命週期 life circle
![lifecircle](https://vuejs.org/images/lifecycle.png) 
## beforeCreate
Vue組件初始化前，此時抓不到任何Vue實體。
## created
組件按照inject所指定方法，引入父層級組件provider提供的方法，並且開始觀察變數是否有改變。通常所有非同步行為在這階段觸發。
## beforeMount
在組件掛載之前會先檢查是否有使用**el選擇器**(註1)，如果有則會去檢查是否有template要掛載在特定tagName。
==一般都會在這時期向後端請求資料==或者 ==使用methods或者computed== 去做自己想要做的事，例如setinterval或addEventListener之類的方法...等等

註1.在main.js中，這段程式碼很明顯就是黃色區塊。
```javascript=
new Vue({
  render: h => h(App)
}).$mount("#app");
```
Vue類別沒有提供el屬性，將會執行 $mount("#app") 把app組件裡的template掛載到\<div id="app">\</div>下。
![](https://i.imgur.com/xHMewfV.png)


## mounted
這時期template已經掛載進父組件下了，並且監聽資料綁訂的data或watch的變數是否有改變。
若有改變的話將會進入beforeUpdate，沒有改變則等待進入beforeDestroy
## beforeUpdate
在資料變更之前將會呼叫這方法執行組件要做的事。
## Updated
在資料變更後，重新渲染(rerender)呼叫這Updated執行組件要做的事。
## beforeDestroy
記得如果之前有使用setInterval或addEventListener請在這時候移除
## destroyed
這時期組件會銷毀值捯下次再度被呼叫使用在重新進入beforeCreate
# Component
Vue的寫法目前有3種
## 基本組件
```javascript=
 <template>
     <div>{{helloWorld}}</div>
 </template>
 <style lang="scss">
     div{
         background-color:#111;
     }
 </style>
 <script>
 export default{
     name:"HelloWorld",
     data:function(){
         return ({
             helloWorld:"HelloWorld"
         })
     }
 }
 </script>
```
## 渲染函式
```javascript=
 <template>
     <hello-user :name="userName"/>
 </template>
 <script>
 import Vue from "vue";
 const HelloUser = Vue.component("HelloUser",{
     props:["name"]
     template:`
         <span>{{name}}</span>
     `,
 })
 export default{
     components:{
         HelloUser
     },
     data:function(){
         return ({
             userName:"Jessica"
         })
     },
    //提供的方法與上面相同
 }
 </script>
```
```javascript=
 import Vue from "vue";
 const HelloUser = Vue.component("HelloUser",{
     props:["name"],
     data:function(){
         return ({})
     },
     render(h){
         return h('h1','Hello'+this.name)
     }
     //提供的方法與上面相同
 });
 export default{
     components:{
         HelloUser
     }
 }
```
## 狀態組件
狀態組件分成 ==**有狀態組件(Stateful Component)**== 與 ==**無狀態組件(Stateless Component)**==
一般專案資料夾建立時會把**有狀態組件**放在containers資料夾裡，**無狀態組件**則是放在components資料夾
那麼我們來看這兩個組件的定義吧!
#### 有狀態組件(Stateful Component)
1. data裡有狀態
2. 不只接收來自props的外來參數
3. 組件內有computed或methods
#### 無狀態組件(Stateless Component)
1. data裡沒有任何狀態
2. 只接收來自props的外來參數
3. 組件內沒有任何computed或methods

通常有狀態組件會傳遞給無狀態組件參數以及狀態，就像是老鳥叫菜逼八做事一樣的道理，而菜鳥好處就是不斷的被利用(無誤
<iframe src="https://codesandbox.io/embed/affectionate-heisenberg-fc4jc?fontsize=14&hidenavigation=1&module=%2Fsrc%2FApp.vue&theme=dark&view=editor"
     style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
     title="affectionate-heisenberg-fc4jc"
     allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
     sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
   ></iframe>
   
# \<template>\</template>
## slots(插槽)
大部分有開始與結尾的<tagName></tagName>都可以放入<slot></slot>或<slot/>標籤作為組件預設的插槽
### 預設
<iframe src="https://codesandbox.io/embed/slot-default-50po8?fontsize=14&hidenavigation=1&module=%2Fsrc%2FApp.vue&theme=dark&view=editor"
     style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
     title="slot-default"
     allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
     sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
   ></iframe>
   
### 命名插槽

### 插槽資料傳遞
# 流程控制
## v-if
<iframe src="https://codesandbox.io/embed/affectionate-heisenberg-fc4jc?fontsize=14&hidenavigation=1&module=%2Fsrc%2FApp.vue&theme=dark&view=editor"
     style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
     title="affectionate-heisenberg-fc4jc"
     allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
     sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
   ></iframe>

## v-show
```javascript=
    <template>
        <div v-show="">
            <div></div>
        </div>
    </template>
```


## v-for
<iframe src="https://codesandbox.io/embed/agitated-poitras-675w7?fontsize=14&hidenavigation=1&module=%2Fsrc%2FApp.vue&theme=dark&view=editor"
     style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
     title="agitated-poitras-675w7"
     allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
     sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
   ></iframe>

#### 應用
* 無限下拉選單-待施工

## v-on
```javascript=
<template>
    
</template>
```
### 自訂義事件
```javascript=

```
## 資料雙向綁訂
### v-on:input與v-bind:value



### v-model
```javascript=

```
# \<style>\</style>
```javascript=

```
## lang
## scoped

# \<script>\</script>
```javascript=
 <script>
 export default{
     name:"HelloWorld",//組件名稱
     extend: ,//繼承單一組件提供的props、methods...等等
     minxin:[],//混合複數組件提供的props、methods...等等
     porps:{//該組件需引入的屬性
     
     },
     data:function(){//該組件內部預設的狀態
         return ({
             helloWorld:"HelloWorld"
         })
     },
     provider:{//向下提供多個子組件變數
         
     },
     inject:[//注入不同父組件提供的變數
     
     ],
     components:{//掛載其他組件至該組件下面
         
     },
     computed:{
         
     },
     methods:{//該組件提供的方法
     
     },
     watch:{//組件需要手動監聽props
     
     },
 }
 </script>
```
## name
## extend
## mixin
## data
## components
## props
## computed
## methods
## watch
```javascript=
<script>
export default{
    props:{
        name:{
            type: String,
            default: "Jessica"
        }
    }
    watch:{
        name:{//觀察props裡面的name
            immediate: false,
            deep: false,
            handler:function(newValue,oldValue){
        
            }
        }
    }
}        
</script>
```
### 提供的屬性
**immdiate** 當組件beforeCreate初始化時觀察指定的變數是否有變動，如有變動則會呼叫handler
**deep**     當觀察的值是Object時會須設定true
**handler**  每當資料變動時會呼叫函式，提供了變更前與變更後的值
### 使用方式
#### props
```javascript=
<script>
export default{
    props:{
        name:{
            type: String,
            default: "Jessica"
        }
    }
    watch:{
        name:{
            immediate: true,
            handler:function(newValue,oldValue){
        
            }
        }
    }
}        
</script>
```
#### data
```javascript=
<script>
export default{
    data:function(){
        return({
            name:"Jessica"
        })
    }
    watch:{
        name:{
            handler:function(newValue,oldValue){
        
            }
        }
    }
}
</script>
```
#### Object裡的值
```javascript=
<script>
export default{
    data:function(){
        return({
            user:{
                name:"Jessica",
                height: 163
            }
        })
    }
    watch:{//對象為height時由於值的型態不是Object
        "user.height":{
            handler:function(newValue,oldValue){
        
            }
        },
        user:{//對象為Object
            deep:true
            handler:function(newValue,oldValue){
        
            }
        }
    }
}
</script>
```
#### Array
```javascript=
<script>
export default{
    data:function(){
        return({
            user:[
                {
                    name:"Jessica",
                    height: 163
                },{
                    name:"John",
                    height: 176
                }
            ]
        })
    }
    watch:{
        "user.height":{
            deep:true,
            handler:function(newValue,oldValue){
        
            }
        }
    }
}
</script>
```

# 第三方套件
[awesome-vue](https://github.com/vuejs/awesome-vue)
# Q&A

# 雷坑
1. 當使用v-for或v-if時，如果其他的節點樹結構相同，必須在結構上加上key，否則會將VNode的資料進行保留，造成資料更新不完全。