#### vue note
---
1、vue.js是什么?
? 構(gòu)建數(shù)據(jù)驅(qū)動(dòng)的web應(yīng)用開(kāi)發(fā)框架
2尺碰、為什么如此受歡迎皿哨?
? -聲明式渲染, 符合前后端分離的趨勢(shì)
? -漸進(jìn)式框架问顷, 適應(yīng)葛總業(yè)務(wù)需求及場(chǎng)景
? -快速交付, 可以結(jié)合各種第三方UI框架
? -企業(yè)需求 , 必備技能
3实胸、MVC,MVP番官,MVVM架構(gòu)模型對(duì)比
? -MVC:Controller薄庐完,view 厚, 業(yè)務(wù)邏輯大多集中在View徘熔。
? -MVVM:MVVM是認(rèn)為Controller做了太多數(shù)據(jù)加工的事情门躯,所以MVVM把`數(shù)據(jù)加工`的任務(wù)從`Controller`中解放了出來(lái),使得`Controller`只需要專(zhuān)注于數(shù)據(jù)調(diào)配的工作酷师,`ViewModel`則去負(fù)責(zé)數(shù)據(jù)加工并通過(guò)通知機(jī)制讓View響應(yīng)ViewModel的改變讶凉。(vue并不是完全遵守MVVM模型)雙向數(shù)據(jù)綁定 染乌,view的變動(dòng)映射在viewmodel,反之一樣懂讯。
? -MVP:view薄荷憋,不部署任何業(yè)務(wù)邏輯,被稱(chēng)為被動(dòng)視圖(passive view)
---
``` html
<div id="box">
? ? {{name}}
? ? <span>{{age}}</span>
? ? <div>{{htmlname}}</div> //此處只是添加文本褐望,無(wú)法添加html標(biāo)簽,支持加減乘除勒庄、三目運(yùn)算,位運(yùn)算等
? ? <p v-htlm="showhtml">ss</p>
? ? <p v-if="isShow">
? ? ? ? 動(dòng)態(tài)添加和刪除? # 直接刪除
? ? </p>
? ? <p v-show="isShow">
? ? ? ? 動(dòng)態(tài)顯示和隱藏? # display:none
? ? </p>
<button v-on:click="handleClick">?
? ? </button>
? ? <div v-bind:class="isShow?'sss':'ddd'">?
? ? ? ? v-bind=:
? ? </div>
</div>
<script type="text/javascript">
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? ? ? name:"xiaoming",? // vue中的變量改變時(shí)瘫里,會(huì)動(dòng)態(tài)渲染前端頁(yè)面实蔽,如果頁(yè)面有使用到此變量
? ? ? ? ? ? age:18,
? ? ? ? ? ? htmlname: "<b>xiaoming</b>",
? ? ? ? ? ? showhtml:"<b>xiaoming</b>",
? ? ? ? ? ? isShow:true,
? ? ? ? }
? ? ? ? methods:{
? ? ? ? ? ? met:function(){
? ? ? ? ? ? console.log('111')
? ? ? ? }
? ? ? ? ? ? handleClick(){
? ? ? ? ? ? ? ? console.log(11);
? ? ? ? ? ? ? ? this.name = "asd";
? ? ? ? ? ? ? ? this.age = true;
? ? }
? ? }
? ? })
</script>
```
*計(jì)算屬性*
```html
<div id="box">
? ? {{name.substring(0,1).toUpperCase()+name.substring(1)}}
? ? <span>{{age}}</span>
? ? <div>計(jì)算屬性{{changeword}} </div>
? ? <div>普通方法{{changewordmethod}} </div>
</div>
<script type="text/javascript">
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? ? ? name:"xiaoming",
? ? ? ? ? ? age:18,
? ? ? ? }
? ? ? ? methods:{
? ? ? ? changewordmethod:function(){ # 每次加載都會(huì)重新計(jì)算,因?yàn)樗瞧胀ǚ椒?/p>
? ? ? ? return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
? ? }
? ? }
? ? ? ? computed:{ // 涉及到此屬性參與的谨读,頁(yè)面都會(huì)重新渲染局装,在普通方法中,如果方法被兩次調(diào)用劳殖,name會(huì)計(jì)算兩次铐尚,但是計(jì)算屬性只計(jì)算一次,并且緩存起來(lái)(如果屬性參數(shù)或者其依賴(lài)改變哆姻,name也會(huì)重新計(jì)算)
? ? ? ? changeword:function(){
? ? ? ? return this.name.substring(0,1).toUpperCase()+this.name.substring(1)
? ? }
? ? }
? ? })
</script>
```
*watch VS computed*
```html
<div id="box">
? ? <P>單價(jià):<input type="text" v-model="price" /> </P>
? ? {{price}}
? ? <P>數(shù)量::<input type="text" v-model="number" /> </P>
{{number}}
? ? <P>總額:<span> {{sum}}</span> </P>
</div>
<script type="text/javascript">
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? ? ? price:100,
? ? ? ? ? ? number:10,
? ? ? ? ? ? sum:?
? ? ? ? }
? ? ? ? ? ? watch:{
? ? ? ? ? ? price:function(newvalue){
? ? ? ? ? ? ? ? this.sum = newvalue*this.number
? ? },
? ? ? ? ? ? number:function(newvalue){
? ? ? ? this.sum = newvalue*this.price
? ? }
? ? ? ? }
? ? ? ? computed:{
? ? ? ? ? ? computedsum:function(){
? ? ? ? ? ? ? ? return this.number*this.name
? ? ? ? ? ? }
? ? ? ? }
? ? })
</script>
```
*setter*
```html
<div id="box">
? ? <p class="default" :class="isShow?'aa':'bb'">class樣式</p>
? ? <div class="default" :class="active:isShow,show:isShow2">class樣式</div>
? ? <p class="default" :class="[who塑径, 'show']"> </p>
? ? // 省略 v-bind -> :
? ? <p class="default" :style="{background: color}"> style樣式</p>
? ? // 和上面的等同, 都是響應(yīng)式的
? ? <p class="default" v-bind:style="obj"> style樣式</p>
</div>
<script type="text/javascript">
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? ? ? name:xiaoming,
? ? ? ? ? ? isShow:false,
? ? ? ? ? ? isShow2:true,?
? ? ? ? ? ? who: "可變變量",
? ? ? ? ? ? cloor: "red",
? ? ? ? ? ? obj:{
? ? ? ? ? ? ? ? background:"red",
? ? ? ? ? ? ? ? fontSize:"30px"
? ? ? ? ? ? }
? ? ? ? }
? ? })
</script>
```
**v-if*? v-show **動(dòng)態(tài)創(chuàng)建和刪除DOM節(jié)點(diǎn)? 動(dòng)態(tài)隱藏和顯示
```html
<div id="box">
// 互斥的兩個(gè)vue標(biāo)簽 如果v-if一開(kāi)始是假,那么不會(huì)創(chuàng)建此節(jié)點(diǎn) 如果有多個(gè)標(biāo)簽受同一個(gè)變量影響填具,寫(xiě)起來(lái)會(huì)比較煩统舀,可以考慮提出這些v-if和v-else,放在同一個(gè)容器下劳景,統(tǒng)一控制容器誉简,但可能會(huì)破話(huà)布局
? ? <P v-if="isCreated">我是v-if創(chuàng)建 </P>?
? ? <P v-else="isCreated">我是v-else創(chuàng)建</P>
? ? <P v-if="isCreated">我是v-if創(chuàng)建 </P>?
? ? <P v-else="isCreated">我是v-else創(chuàng)建</P>
? ? // template標(biāo)簽并不會(huì)實(shí)質(zhì)性的去創(chuàng)建template標(biāo)簽,只是一個(gè)虛擬的控制性容器
? ? <template v-if="isCreated">
? ? ? ? <P v-if="isCreated">我是v-if創(chuàng)建 </P>?
? ? ? ? <P v-else="isCreated">我是v-else創(chuàng)建</P>
? ? ? ? <P v-if="isCreated">我是v-if創(chuàng)建 </P>?
? ? ? ? <P v-else="isCreated">我是v-else創(chuàng)建</P>
? ? </template>
? ? // 動(dòng)態(tài)隱藏和顯示 如果一開(kāi)始是假盟广,那么創(chuàng)建出節(jié)點(diǎn)闷串,并且為節(jié)點(diǎn)加上display=none
? ? <div v-show="isCreated">
? ? ? ? 動(dòng)態(tài)隱藏和顯示
? ? </div>
</div>
<script type="text/javascript">
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? ? ? isCreated:false,
? ? ? ? }
? ? })
</script>
```
**v-for** 把一個(gè)數(shù)組對(duì)應(yīng)為一組元素,可以在模板渲染時(shí)進(jìn)行遍歷筋量,顯示
```html
<div id="box">
? ? <ul>
? ? ? ? // 遍歷顯示
? ? ? ? <li v-for="data in datalist"> {{data}}</li>
? ? </ul>
? ? <ul>
? ? ? ? // 索引和元素的共同取用,用 in和of的效果是相同的
? ? <li v-for="(data,index) in datalist"> {{data}}-----{{index}}</li>
? ? </ul>
? ? <input type="text", v-model="mytext" />
? ? <li v-for="data in computeddatalist"> {{data}} </li>
</div>
<script type="text/javascript">
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? ? ? // 在vue中烹吵,push、pop桨武、shift肋拔、unshift、splice呀酸、sort凉蜂、reverse等方法都是可以改變下面的datalist的,并且,vue會(huì)對(duì)頁(yè)面進(jìn)行重新渲染窿吩;但是數(shù)組如果并未產(chǎn)生實(shí)際性的變動(dòng)時(shí)(filter茎杂,concat,slice等)纫雁,頁(yè)面并不會(huì)重新渲染煌往,但可以重新給 通過(guò)給數(shù)組進(jìn)行賦值來(lái)實(shí)現(xiàn)動(dòng)態(tài)刷新
? ? ? ? ? ? datalist:["aaa", "bbb", "ccc"],
? ? ? ? ? ? mytext:""
? ? ? ? }
? ? ? ? computed:{
? ? ? ? computeddatalist:function(){
? ? ? ? return this.datalist.filter(item=>item.indexOf(this.mytext)>-1)
? ? }
? ? }
? ? })
</script>
```
**鍵盤(pán)事件監(jiān)聽(tīng)**
```html
<div id="box">
? ? <button @click="count=count-1">-</button>
? ? <p>{{count}}</p>
? ? <button @click="count=count+1">+</button>
? ? <p>{{name}}</p>
? ? <button @click="handleClick">click</button>
// 直接在事件中定義想要傳的參數(shù)
? ? <button @click="handleClick2('1111', '22222', $event)">click2</button>
? ? // 只有事件源是自身的時(shí)候,事件才會(huì)發(fā)生轧邪,否則不會(huì)觸發(fā)事件
? ? <ul @click.self="handleUlClick">
? ? ? ? // 阻斷冒泡
? ? ? ? <li @click.stop="handleClick">111</li>
? ? ? ? // 點(diǎn)擊只有第一次是有效的携冤,后續(xù)不會(huì)再次觸發(fā)
? ? ? ? <li @click.once="handeOnce">222</li>
? ? ? ? <li>333</li>
? ? </ul>
? ? // 只有在摁下enter的情況下才會(huì)觸發(fā)事件 同理 enter,tab,esc,space,up,down,left,right
? ? <input type="text" @keyup.enter="handleKeyUp" />
</div>
<script type="text/javascript">
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? ? ? count:1,
? ? ? ? ? ? name: "xiaoming"
? ? ? ? },
? ? ? ? methods:{
? ? ? ? ? ? handleClick(ev){
? ? ? ? ? ? ? ? // ev就是事件的觸發(fā)源
? ? ? ? ? ? ? ? console.log(ev.target.value);
? ? ? ? ? ? ? ? this.name="aaa";
? ? ? ? ? ? },
? ? ? ? ? ? handleclick2(data1, data2, ev){
? ? ? ? ? ? ? ? console.log(data1);
? ? ? ? ? ? ? ? console.log(data2);
? ? ? ? ? ? ? ? console.log(ev.target)
? ? ? ? ? ? },
? ? ? ? ? ? handleClick(){
? ? ? ? console.log("li點(diǎn)擊");
? ? }闲勺,
? ? ? ? ? ? handleUlClick(){
? ? ? ? ? ? ? ? console.log("ul點(diǎn)擊")
? ? ? ? ? ? }
? ? ? ? ? ? handleKeyUp(ev){
console.log(ev.keyCode);
? ? ? ? ? ? ? ? if(ev.keyCode==13){
? ? ? ? ? ? ? ? ? ? console.log(ev.target)
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? })
</script>
```
**表單輸入綁定**
```html
<div id="box">
// 輸入框中輸入的值和外面的值是相互綁定的
<input type="text" v-model="mytext" />
? {{mytext}}
? ? <p>
? ? ? ? <imput type="checkbox" v-mdoel="isChecked">記住用戶(hù)名?
? ? </p>
? ? // 每次勾選都會(huì)在checkgroup添加一個(gè)checkbox的value值,取消勾選會(huì)在checkgroup中再次移除
? ? <p><input type="checkbox" v-model="checkgroup" value="1"/>aaa</p>
? ? <p><input type="checkbox" v-model="checkgroup" value="2"/>bbb</p>
? ? <p><input type="checkbox" v-model="checkgroup" value="3"/>ccc</p>
? ? // vue提供的單選框功能扣猫,無(wú)須獲取dom節(jié)點(diǎn)菜循,直接訪問(wèn)picked
? ? <p><input type="raido" v-model="picked" value="vue"/>{{picked}}</p>
? ? // 此處在輸入框內(nèi)修改輸入的內(nèi)容,外面的name并不會(huì)隨之改變申尤,但是當(dāng)鼠標(biāo)移走之后癌幕,外部的那么值會(huì)立刻改變,此為lazy昧穿。如果想限制輸入的內(nèi)容必須為數(shù)字的話(huà)勺远,可以把lazy換位.number,如果想去除輸入內(nèi)容的頭尾空格时鸵,那么可以把lazy換位trim
? ? <p><input type="text" v-model.lazy="name" value=""/>{{name}}</p>
</div>
<script type="text/javascript">
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? ? ? name:xiaoming,
? ? ? ? ? ? mytext:"111",
? ? ? ? ? ? isChecked:false,
? ? ? ? ? ? checkgroup:[],
? ? ? ? ? ? picked:"vue",
? ? ? ? }
? ? })
</script>
```
**組件的使用**封裝的胶逢,可重用的html
*組件分為全局組件和局部組件
```html
<div id="box">
? ? <hello></hello>
<hellobox></hellobox>
</div>
<div id="box2">
? ? // 重新初始化后可以復(fù)用全局組件
? ? <hello></hello>
? ? //下面這個(gè)并不會(huì)被渲染出來(lái),會(huì)報(bào)錯(cuò)饰潜,因?yàn)閔ellobox是box的獨(dú)有的
? ? <hellobox></hellobox>
</div>
<script type="text/javascript">
? ? // 父子組件的狀態(tài)是無(wú)法共享的
? ? Vue.component("hello",{
? ? ? ? ? ? template:
? ? ? ? `
? ? ? ? ? ? ? ? <div>
? ? ? ? ? ? ? ? 一個(gè)hello組件{{name}}
<ul>
// datalist 也必須用函數(shù)方法定義出來(lái)
? ? <li v-for="data in datalist>{{data}}</li>
? ? </ul>
? ? </div>
`
? ? ? ? // data:"name" 在組件中初坠,這是無(wú)法使用的,并且會(huì)報(bào)錯(cuò)彭雾,必須定義為方法碟刺,才可以調(diào)用
? ? ? ? data:function(){
? ? ? ? ? ? return {
name:"xiaoming",
? ? ? ? ? ? ? ? datalist:['aaa', 'bbb']
? ? ? ? ? ? }
? ? }
? ? })
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? },
? ? ? ? components:{
? ? ? ? ? ? "hellobox":{
? ? ? ? ? ? ? ? template:
? ? ? ? ? ? `<div>box下面獨(dú)有的組件,非全局組件</div>`
? ? ? ? ? ? }
? ? ? ? }
? ? var vm2 = new Vue({
? ? ? ? el:"#box2",
? ? ? ? data:{
? ? }
? ? })
})
</script>
```
**組件之間的通信**父子組件
使用vue綁定自定義事件:
每個(gè)Vue的實(shí)例都實(shí)現(xiàn)了事件的接口:
* 使用 $on(eventname)監(jiān)聽(tīng)事件薯酝;
* 使用$emit(evenvname)觸發(fā)事件半沽;
? ```html
? <div id="box">
? ? ? // hello里面的handleparentclick是父組件定義的監(jiān)聽(tīng),也就是說(shuō)這個(gè)事件監(jiān)聽(tīng)是父組件進(jìn)行的
? ? ? <hello name="xiaoming" :age="100" @event="handleParentClick"></hello>
? </div>
? <script type="text/javascript">
? ? ? var obj = {
? ? ? ? ? template:`
? <div> 我是{{name}}---{{age}}組件</div>
? //
? <button @click="handleclick">click</click>
? `,
? ? ? ? ? // 接收子組件的一些屬性值吴菠,并存儲(chǔ)者填,props是單向的,
? ? ? ? ? props: {
? ? ? ? ? name:String,
? ? ? ? ? ? ? age:Number,
? ? ? ? ? },
? ? ? }
? ? ? var vm = new Vue({
? ? ? ? ? el:"#box",
? ? ? ? ? data:{
? ? ? ? ? },
? ? ? ? ? components:{
? ? ? ? ? ? ? hello: obj
? ? ? ? ? },
? ? ? ? ? methods:{
? ? ? ? ? ? ? handleParentClick(){
? ? ? ? ? ? ? ? ? console.log("parent_click", "click")
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? })
? </script>
? ```
```html
<div id="box">
? ? <hello name="xiaoming"></hello>
</div>
<script type="text/javascript">
? ? var obj = {
? ? ? ? template:`
<div> 我是{{name}}組件</div>
`,
? ? ? ? // 接收子組件的一些屬性值做葵,并存儲(chǔ)幔托,props是單向的,
? ? ? ? props: ["name"]
? ? }
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? },
? ? ? ? components:{
? ? ? ? ? ? hello:{
? ? ? ? ? ? }
? ? ? ? }
? ? })
</script>
```
**非父子組件之間的通信**
vue的非父子 組件之間的通信一般有兩種方法:
-- 中央事件總線 bus=new Vue();
* mounted生命周期中進(jìn)行監(jiān)聽(tīng)
# --vuex 狀態(tài) 管理? 后面再說(shuō)這個(gè)
```html
<div id="box">
? ? <hello name="xiaoming"></hello>
</div>
<script type="text/javascript">
? ? var bus = new Vue()
? ? var helloA = {
? ? ? ? template:`
<div>我是組件A
<button @click="handleClick>click</button>
</div>
`
? ? ? ? ,
? ? ? ? methods:{
? ? ? ? ? ? handleClick(){
? ? ? ? ? ? ? ? //將要發(fā)消息給B組件
? ? ? ? ? ? ? ? bus.$emit("xiaoming", "來(lái)自組件A的消息")
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? var helloB = {
? ? ? ? template:`
? ? ? ? <div>我是組件B</div>
? ? ? ? `,
? ? ? ? //組件生命周期
? ? ? ? mounted(){
? ? ? ? ? ? console.log("b組件掛在的鉤子函數(shù)");
? ? ? ? ? ? bus.$on("xiaoming", function(value){
? ? ? ? ? ? ? console.log(value)
? ? ? ? ? ? })
? ? ? ? }
? ? }
? ? var vm = new Vue({
? ? ? ? el:"#box",
? ? ? ? data:{
? ? ? ? },
? ? ? ? components:{
? ? ? ? ? ? helloA:helloA,
? ? ? ? ? ? helloB:helloB,
? ? ? ? },
? ? ? ? methods:{
? ? ? ? ? ? handleParentClick(data){
? ? ? ? ? ? ? ? console.log("parent", data);
? ? ? ? ? ? }
? ? ? ? }
? ? })
</script>
```
**slot插槽分發(fā)**
``` html
<div id="box">
? ? <hello name="xiaoming">
? ? <button @click="handleClick" slot="leftbutton">leftbutton</button>
? ? ? ? <span slot="content">title_content</span>
? ? ? ? <button @click="handleClick" slot="rightbutton">rightbutton</button>
? ? </hello>
? ? <hello>
? ? <span slot="content">標(biāo)題內(nèi)容</span>
? ? <button @click="handleClick" slot="rightButton">右側(cè)按鈕</button>
? ? </hello>
? ? <hello>
? ? <button @click="handleClick" slot="leftbutton">左側(cè)按鈕</button>
? ? ? ? <span slot="content">標(biāo)題內(nèi)容</span>
? ? </hello>
</div>
<script type="text/javascript">
? ? var obj = {
? ? ? ? template:`<div>
? ? ? ? ? ? <slot name="leftbutton></slot>
? ? ? ? ? ? <slot name="content></slot>
? ? ? ? ? ? <slot name="rightbutton></slot>
div>
`
? ? }
? ? new Vue({
? ? ? ? el:#box,
? ? ? ? data:{
? ? },
? ? components:{
hello:obj
? ? ? ? ? ? }? ?
? ? },
? ? methods:{
? ? ? ? handleClick(){
? ? ? ? ? ? console.log("button_click")
? ? ? ? }
? ? ? ? }
? ? )
</script>
```
**動(dòng)態(tài)組件**
* component元素,動(dòng)態(tài)的綁定多個(gè)組件到它的
* keep-alive重挑,保留狀態(tài)嗓化,避免組件重新渲染
```html
<div id="box">
<keep-alive>
? ? ? ? <component :is="current"></component>
? ? </keep-alive>
? ? <footer>
? ? <ul>
? ? ? ? ? ? <li @click="handleclick('home')">home</li>
? ? ? ? ? ? <li @click="handleclick('list')">list</li>
? ? ? ? ? ? <li @click="handleclick('shopcar')">shopcar</li>
? ? ? ? </ul>
? ? </footer>
</div>
<script type="text/javascript">
? ? var home = ({
? ? ? ? template:`
<div>home組件</div>
`
? ? })
? ? var list = ({
? ? ? ? template:`
<div>list</div>
`
? ? })
? ? var shopcar = ({
? ? ? ? template:`
<div>shopcar</div>
`
? ? })
</script>
```