vue筆記

vue基礎
template   是一個標籤可是在頁面不顯示  vue自帶的標籤
 
 
設計模式(MVC/MVP/MVVM)的區別
Vue.js(讀音 /vjuː/, 相似於 view)是一個構建數據驅動的 web 界面的漸進式MVVM框架。
設計模式(MVC/MVP/MVVM)的對比
MVC (Model View Controller ):
1.視圖(View):用戶界面。
2.控制器(Controller):業務邏輯
3.模型(Model):數據保存
MVC特色:
一、用戶能夠向 View 發送指令(DOM 事件),再由 View 直接要求 Model 改變狀態。
二、用戶也能夠直接向 Controller 發送指令,再由 Controller 發送給 View。
三、Controller 很是薄,只起到路由的做用,而 View 很是厚,業務邏輯都部署在 View。
MVP(Model View Presenter):
MVP 模式將 Controller 更名爲 Presenter,同時改變了通訊方向。
MVP特色:
一、各部分之間的通訊,都是雙向的。
二、View 與 Model 不發生聯繫,都經過 Presenter 傳遞。
三、 View 很是薄,不部署任何業務邏輯,稱爲"被動視圖"(Passive View),即沒有任何主動性,而 Presenter很是厚,全部邏輯都部署在那裏。
MVVM( Model-View-ViewModel ):
MVVM 模式將 Presenter 更名爲 ViewModel,基本上與 MVP 模式徹底一致。
MVVM特色:
惟一的區別是,它採用雙向綁定(data-binding):View的變更,自動反映在 ViewModel,反之亦然。VUE採用這種模式。
VUE初相識
Vue.js(讀音 /vjuː/, 相似於 view)是一個構建數據驅動的 web 界面的漸進式MVVM框架。正式發佈於2014年2月,2016年4月,發佈2.0版本,創造者-尤雨溪。
vue官網:https://cn.vuejs.org/
Vue的優勢:
一、性能好
二、簡單易用
三、先後端分離
四、單頁面應用(SPA)用戶體驗好,還能夠作轉場動畫
Vue的缺點:
一、不適合seo優化,解決方案服務端渲染(SSR)。
二、模板模式開發,封裝的比較厲害,代碼報錯信息不明確。
三、適合單人開發,適合中小型項目。
VUE數據驅動和雙向綁定
安裝vue
CDN引入:
對於製做原型或學習,你能夠這樣使用最新版本:
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
對於生產環境,咱們推薦連接到一個明確的版本號和構建文件,以免新版本形成的不可預期的破壞:
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
vue-cli3腳手架安裝:
npm install -g @vue/cli
建立項目:
vue create 項目目錄
初始化
<div id="app">
    {{name}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
    new Vue({
        el:"#app",//el根元素名稱
        //初始化數據源方式一(推薦)
        data(){
            return {
                name:"張三"
            }
        }
    });
<div id="app">
    {{name}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        //初始化數據源方式二
        data:{
            name:"張三"
        }
    });
data爲何要用一個方法而不用對象
由於vue是單頁面應用,是由多個組件組成的,每一個組件裏面都有data,若是data是個對象,對象是引用類型,一個組件裏面的data值改變了,其餘組件的值也都會改變,爲了不出現互相引用的問題,咱們要用方法來初始化數據造成一個做用域,防止各個組件互相引用
vue的數據驅動和雙向綁定
v-model:雙向綁定
v-cloak:解決加載閃爍時出現vue標籤或指令符號
雙向綁定的原理
實現雙向綁定的原理就是利用了 Object.defineProperty() 這個方法從新定義了對象獲取屬性值(get)和設置屬性值(set)的操做來實現的。
<input type="text">
<span id="text"></span>
let data={};
    let val='';
    let text=document.getElementById("text");
    Object.defineProperty(data,"value",{
        get:()=>{
            return val;
        },
        set:(pVal)=>{
            val=pVal;
            text.innerHTML=pVal;
        }
    });
window.addEventListener("input",(e)=>{
        data.value=e.target.value;
        console.log(data.value);//若是get方法沒有返回值,獲取的是undefined
    })
vue 中css樣式使用
在vue中使用css樣式:
普通寫法:
<div class=「box」></div>
對象語法:
<div :class=「{box:true,show:true}」></div>
數組語法:
<div :class=「[box,show]」></div>
內聯樣式
對象寫法:
<div :style=「{fontSize:’14px’,width:’100px;’,height:’100px’,badkgroundColor:’#FF0000’}」></div>
數組寫法:
<div :style=「[baseStyles, fonts]」></div>
data(){
    return {
        baseStyles:{
            width:'100px',
            height:'100px',
            backgroundColor:'#FF0000'
        },
        fonts:{
            fontSize:'14px',
            color:'#FFFFFF'
        }
    }
}
模板語法與經常使用指令
v-cloak:防止閃爍解決顯示vue標籤
v-model:多用於表單元素實現雙向數據綁定
v-for:列表渲染
v-show:顯示內容
v-if:顯示與隱藏 (dom元素的刪除添加默認值爲false)
v-else-if:必須和v-if連用
v-else:必須和v-if連用  不能單獨使用  不然報錯   模板編譯錯誤
v-bind:動態綁定  做用: 及時對頁面的數據進行更改,縮寫:
v-html:解析html標籤
事件處理
v-on:click 給標籤綁定函數,能夠縮寫爲@,例如綁定一個點擊函數  函數必須寫在methods裏面
v-on:click.stop:阻止冒泡事件
v-on:click.once:點擊事件只容許一次
v-on:mouseover:鼠標移動元素上
v-on:mouseout:鼠標離開元素
v-on:mousemove:鼠標移動
v-on:touchstart:觸摸開始
v-on:touchmove:觸摸移動
v-on:touchend:觸摸結束
v-on:keyup:鍵盤事件
v-on:keyup.enter:回車鍵
computed計算屬性
computed用來監控本身定義的變量,該變量不在data裏面聲明,直接在computed裏面定義,而後就能夠在頁面上進行雙向數據綁定展現出結果,能夠作邏輯處理的變量。
舉例:購物車裏面的商品列表和總金額之間的關係,只要商品列表裏面的商品數量發生變化,或減小或增多或刪除商品,總金額都應該發生變化。這裏的這個總金額使用computed屬性來進行計算是最好的選擇。
<div id="app" v-cloak>
    商品:html5
 
    價格:{{price}}元
 
    數量:<button type="button" @click="decrease()">減小</button>{{amount}}<button type="button" @click="increase()">增長</button>
 
    金額:{{total}}元
</div>
 
new Vue({
        el:"#app",
        data(){
            return {
                amount:1,
                price:10
            }
        },
        computed:{
            total(){
                return this.amount*this.price
            }
        },
 
       methods:{
            //增長數量
            increase(){
                this.amount++;
            },
            //減小數量
            decrease(){
                if(this.amount>1){
                    this.amount--
                }
            }
        }
    });
watch監聽
watch主要用於監控vue實例的變化,它能夠監控一個data裏面的數據,computed,路由的變化。
特色:
一、監聽獲取兩個值一個是新值,另外一個是舊值
二、能夠深度監聽
三、能夠利用watch監聽路由的特性作轉場動畫
 
<div id="app" v-cloak>
    <button @click="name='李四'">{{name}}</button>
    <button @click="classify.title='品牌男裝'">{{classify.title}}</button>
    <button @click="classify.children.title='下裝'" />{{classify.children.title}}</div>
</div>
 
new Vue({
        el:"#app",
        data(){
            return {
                name:"張三",
                classify:{
                    title:"大媽女裝",
                    children:{
                        title:"上裝",
                        children:{
                            title:"韓都衣舍大媽女裝"
                        }
                    }
                }
            }
        },
 
        computed:{
            getName(){
                return this.name;
            }
        },
        watch:{
            //監聽data裏面的值
            name(newVal,oldVal){
                console.log("newVal:"+newVal,"oldVal:"+oldVal);
            },
            //監聽computed裏面的值
            getName(newVal,oldVal){
                console.log("computed-newVal:"+newVal,"computed-oldVal:"+oldVal);
            },
 
           //引用類型監聽
            "classify.title"(newVal,oldVal){
                console.log(newVal,oldVal);
            },
            //深度監聽
            classify:{
                handler(val){
                    console.log(JSON.stringify(val));
                },
                deep:true
            }
        }
    });
全局組件
Vue.component(’組件名稱’,’組件’)
組件包括:
template
data
methods
生命週期鉤子函數
computed
watch
…….
//定義公共組件
    let PublicComponent={
        template:`
           <div>
                 <span style="font-size:16px;color:#FF0000">我是公共組件</span>
            </div>
        `
    };
    //首頁
    let HomePage={
        template:`
            <div>
                我是{{name}}
                <PublicComp></PublicComp>
            </div>
        `,
        data(){
            return {
                name:"首頁"
            }
        }
    };
    //全局註冊組件
    Vue.component("PublicComp",PublicComponent);
    new Vue({
        el:"#app",
        //掛載要使用的模板
        components:{
            HomePage
        },
        //模板規範必須只能有一個惟一的根元素標籤
        template:`
            <div>
                <PublicComp></PublicComp>
                <HomePage></HomePage>
                我是vue模板
            </div>
        `
    });
全局filter過濾
Vue.filter("increase",function(value,num1,num2){
        return parseInt(value)+parseInt(num1)+parseInt(num2);
    });
var App={
        data:function(){
            return {
                count:1
            }
        },
        template:`<div>數量:{{count|increase(10,20)}}</div>`
    };
局部filter過濾
var App={
        data:function(){
            return {
                count:1
            }
        },
        filters:{
            formatDate:function(val){
                if(val!==''){
                    val=val.split("-");
                    val=val[0]+"年"+val[1]+"月"+val[2]+"日"
                }
                return val;
            }
        },
        template:`<div>日期:{{"2019-09-11"|formatDate}}</div>`
    };
父子組件傳值
父組件給子組件傳值:
<ChildComponent title="我是子組件"></ChildComponent>
子組件用props接受:
第一種方式:
props:[‘title’] //數組方式接收
第二種方式(官方推薦):
props:{
     title:{
          type:String //數據類型
          required:true //是否必須傳值,true:必須,false:可選
     }
}
子組件給父組件傳值:
子組件代碼:
<button type="button" @click="sendParent()">給父組件傳值</button>
methods:{
    sendParent(){
        this.$emit("getChild","我是子組件傳過來的值");
    }
}
父組件代碼:
<ChildComponent title=「我是子組件」 @getChild="getParent($event)"></ChildComponent>
methods:{
getParent(data){//接收父組件HomeComponent傳過來的值
        console.log(data);
    }
}
兄弟組件傳值
//定義一個總線bus
let bus=new Vue;
//A組件
let AComponent={
    template:`
       <div>
        <button type="button" @click="sendB()">給B組件傳值</button>
       </div>
    `,
    data(){
        return {
        }
    },
    methods:{
        sendB(){
            bus.$emit("getA","你好");//用$emit傳值
        }
    }
}
 
let BComponent={
    template:`
        <div>
            A組件傳過來的值:{{text}}
        </div>
    `,
    data(){
        return{
            text:""
        }
    },
    created(){
//用$on接收
        bus.$on("getA",(message)=>{
            console.log(message);
            this.text=message;
        })
    }
}
父組件與子組件實現雙向綁定
方法一:
父組件
new Vue({
        el:"#root",
        data(){
          return{
              value:」張三」
          }
        },
        components:{Comp:component},
        template:`<div><Comp v-model="value"></Comp>{{value}}</div>`
    }
    )
 
子組件
const component={
        template:`
            <div>
                <input type="text" v-model="currentValue">
            </div>
        `,
        props: {
            // 接收一個由父級組件傳遞過來的值
            value: {
                type: String
            }
        },
        created(){
            console.log(this.value)//接收父組件的值
        },
        computed:{
            currentValue: {
                // 動態計算currentValue的值
                get:function() {
                    return this.value; // 將props中的value賦值給currentValue
                },
                set:function(val) {
                    this.$emit('input', val); // 經過$emit觸發父組件
                }
            }
        }
    }
 
方法二:
父組件
new Vue({
        el:"#root",
        data(){
          return{
              name:"張三"
          }
        },
        components:{Comp:component},
        template:`
            <div><Comp v-model="name"></Comp>{{name}}</div>
        `
    }
    )
子組件
const component={
        template:`
            <div>
                <input type="text" @input="changeName">
            </div>
        `,
        model: {
            prop:"name",//props裏面的name
            event:"change"//$emit裏面的事件change
        },
        props: {
            // 接收一個由父級組件傳遞過來的值
            name: {
                type: String
            }
        },
        methods:{
            changeName(e){
                this.$emit("change",e.target.value);
            }
        }
    }
ref的使用
<div class="box" ref="box1">box1</div>
<div class="box" ref="box2">box2</div>
<div class="box" ref="box3">box3</div>
console.log("當前:"+this.$refs.box1.innerHTML);
//父div
console.log("父div:"+this.$refs.box1.parentNode.innerHTML);
//下一個元素
console.log("下一個元素:"+this.$refs.box1.nextElementSibling.innerHTML);
//上一個元素
console.log("上一個元素:"+this.$refs.box2.previousElementSibling.innerHTML);
父組件調用子組件裏面的方法:
<ChildComponent ref="child"></ChildComponent>
一、給子組件加上ref=「child」
二、在父組件使用:
this.$refs.child.send();//send()就是子組件裏面的方法
Mixins混入
混入 (mixin) 提供了一種很是靈活的方式,來分發 Vue 組件中的可複用功能。
let base={
        data(){
            return {
                visible:true
            }
        },
        methods:{
            toggle(){
                this.visible=!this.visible
            }
        }
    };
 
   let Acomponent={
        template:`
          <div>
          <button type="button" @click="toggle()">顯示/隱藏a組件</button>
          <div v-show="visible">我是A組件</div>
          </div>
        `,
        mixins:[base]
    };
 
   let Bcomponent={
        template:`
           <div>
                <button type="button" @click="toggle()">顯示/隱藏b組件</button>
                <div v-show="visible">我是b組件</div>
           </div>
        `,
        data(){
            return {
                visible:true //覆蓋mixins裏面的visible
            }
        },
        mixins:[base]
    };
slot插槽
能夠獲取組件裏的內容。
應用場景:自定義組件使用,好比自定義button按鈕。
let ButtonComponent={
    template:`
            <button type="button" class="btn"><slot></slot></button>
    `,
mounted:function(){
      //獲取插槽裏的內容
      if(this.$slots.default!=null){
        console.log(this.$slots.default[0].elm.innerHTML);
      }
    },
};
new Vue({
    el:"#app",
    components:{
        'my-button':ButtonComponent
    },
    template:`<div>
        <my-button>提交</my-button>
    </div>`
})
transition 過分/動畫
<transition name=「fade」>
     <div class=「box」></div>
</transistion>
.fade-enter{ } 進入過渡的開始狀態,元素被插入時生效,只應用一幀後當即刪除。(運動的初始狀態)
.fade-enter-to{} (2.1.8版及以上) 定義進入過渡的結束狀態。
.fade-enter-active{ } 定義進入過渡生效時的狀態。在整個進入過渡的階段中應用,在元素被插入以前生效,在過渡/動畫完成以後移除。這個類能夠被用來定義進入過渡的過程時間,延遲和曲線函數。
.fade-leave{ } 離開過渡的開始狀態,元素被刪除時觸發,只應用一幀後當即刪除;
.fade-leave-to{} (2.1.8版及以上) 定義離開過渡的結束狀態。
.fade-leave-active{ } 定義離開過渡生效時的狀態。在整個離開過渡的階段中應用,在離開過渡被觸發時馬上生效,在過渡/動畫完成以後移除。這個類能夠被用來定義離開過渡的過程時間,延遲和曲線函數。
配合animate.css實現動畫效果:
animate官網:https://daneden.github.io/animate.css/
<button @click="isShow = !isShow">
    Toggle render
</button>
<transition name="custom" enter-active-class="animated tada" leave-active-class="animated bounceInRight">
                     <div class="box" v-show="isShow"></div>
</transition>
data(){
    return {
        isShow:true
    }
}
 
<transition-group name="slide">
    <div class="banner-slide" v-show=」true" :key=」1"><img src=」1.jpg" alt=""></div>
    <div class="banner-slide" v-show=」false" :key=」2"><img src=」2.jpg" alt=""></div>
</transition-group>
.slide-enter-active,.slide-leave-active{transition:all 1s;position:absolute;}
.slide-enter{
    opacity:0;
}
.slide-enter-to{
    opacity:1;
}
.slide-leave{
    opacity:1;
}
.slide-leave-to{
    opacity:0;
}
生命週期
beforeCreate:初始化以前
created:初始化完成(不能獲取dom,通常用於獲取ajax數據)
beforeMount:掛載以前
mounted:掛載完成以後
beforeUpdate:數據更新以前
updated:數據更新以後
beforeDestroy:解除綁定以前(頁面離開)
destroyed:解除綁定以後(頁面離開)
activated:keep-alive組件激活時調用。該鉤子在服務器端渲染期間不被調用。用於性能優化緩存dom和數據。
deactivated:keep-alive組件停用時調用。該鉤子在服務端渲染期間不被調用。
swiper插件和nextTick的使用
官網:https://www.swiper.com.cn/
nextTick:在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。
vue腳手架
安裝vue腳手架
npm install -g @vue/cli
卸載vue腳手架
npm uninstall vue-cli -g
查看版本號
vue -V
幫助建立項目
vue --help
建立項目
vue create 項目名稱
安裝第三方插件
之前安裝
npm install --save axios
如今能夠用
vue add axios
.env配置全局變量和區分開發者環境和生產環境
全局變量
在根目錄下面建立.env文件
內容:
VUE_APP_URL=http://vueshop.glbuys.com
注意命名規範:必須VUE_APP_開頭
開發者全局變量
在根目錄下建立.env.development文件
內容
VUE_APP_URL="http://vueshop.glbuys.com/api"
生產環境全局變量
在根目錄下建立.env.production文件
內容
VUE_APP_URL="https://vueshop.glbuys.com/api"
讀取值:
process.env.VUE_APP_URL
運行生成環境的文件
一、安裝serve服務器
npm install -g serve
二、運行方式一:
serve -s dist
運行方式二:
cd dist
serve
vue.config.js的配置
根目錄創建vue.config.js
在module.exports={}裏面配置
一、配置根目錄
publicPath:'/’
二、構建輸出目錄
outputDir:'dist'
三、 靜態資源目錄(js,css,image)
assetsDir:"assets"
四、是否開啓eslint檢測
lintOnSave:false //false不開啓,有效值:true || false
 
服務器配置:
devServer:{
open:false, //是否啓動打開瀏覽器
host:"localhost",//主機,0.0.0.0支持局域網地址,能夠用真機測試
port:8080, //端口
https:false,//是否啓動https
       //配置跨域代理
      proxy:{
            "/api":{
            target:"http://vueshop.glbuys.com/api",
            changeOrigin:true,
            pathRewrite:{
                   '^/api':""
            }
            }
       }
}
mockjs的使用
mockjs的官網:http://mockjs.com/
mockjs是一個模擬json數據的測試工具。
安裝mockjs
npm install mockjs --save-dev
 
新建mork.js
import Mock from 'mockjs';
Mock.mock('/api/news',"get",{
    'data|10':[
        {
            'id|+1':1,
            'title|+1':Mock.Random.cword(8,20),
            'image|+1':Mock.Random.image('200x100', Mock.Random.color()),
            'date|+1':Mock.Random.date('yyyy-MM-dd')
        }
    ]
});
});
 
導入mock.js
import "./js/mock.js";
$.ajax({
url:"/api/news",
type:"get",
dataType:"json",
success:function(res){
   console.log(res.news);
}
}
})
eslint的使用  --和嚴格模式差很少
官網:http://eslint.cn
eslint的做用:
1. 提供編碼規範;
2. 提供自動檢驗代碼的程序,並打印檢驗結果:告訴你哪個文件哪一行代碼不符合哪一條編碼規範,方便你去修改代碼。
 
最經常使用的兩個命令:
/*eslint-disable*/ 禁用eslint檢測
/*eslint-enable*/ 開啓eslint檢測
移動端佈局及適配方式
viewport使用
<meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1.0,user-scalable=no" />
width:設置layout viewport 的寬度,爲一個正整數,或字符串"device-width"
initial-scale:設置頁面的初始縮放值,爲一個數字,能夠帶小數
minimum-scale:容許用戶的最小縮放值, 爲一個數字,能夠帶小數
maximum-scale:容許用戶的最大縮放值,爲一個數字,能夠帶小數
height:設置layout viewport 的高度,這個屬性對咱們並不重要,不多使用
user-scalable:是否容許用戶進行縮放,值爲"no"或"yes", no 表明不容許,yes表明容許
 
format-detection使用
<meta name=「format-detection」 content=「telephone=no,email=no,date=no,address=no」 />
telephone:電話
eamil:郵箱
date:日期
address:地址
 
移動端如何作適配?
採用rem做爲佈局單位。
什麼是rem?
rem是CSS3新增的相對長度單位,是指相對於根元素html的font-size計算值的大小。
簡單可理解爲屏幕寬度的百分比。
rem與em的區別?
rem是針對根元素的html的font-size計算值大小計算的。
em是根據父元素的font-size大小計算的。
 
使用手淘flexible.js計算rem
好比:750px設計稿,那麼1rem=75px, div的高是50px ,50px換算成rem公式:
50px/75px=0.7rem;
解決1px細線問題
問題出現緣由:
在retina(視網膜)屏上面, devicePixelRatio(物理像素)這個值是2或3, 因此1px長度映射到物理像素上就有2px或3px那麼長。
 
解決方案:
viewport + rem 方案
<meta name=「viewport」 content=「initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no」 />
接下來的任務就是js的動態修改縮放比 以及 實現rem根元素字體大小的設置。
var viewport = document.querySelector("meta[name=viewport]");
if (window.devicePixelRatio == 1) {
     viewport.setAttribute('content', 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no')
}
if (window.devicePixelRatio == 2) {
       viewport.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no')
}
if (window.devicePixelRatio == 3) {
     viewport.setAttribute('content', 'width=device-width, initial-scale=0.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
}
var docEl = document.documentElement;
var fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;
面試解答:
判斷devicePixelRatio物理像素若是爲1,設置viewport縮放大小爲1,若是爲2設置viewport縮放大小爲0.5,若是爲3設置viewport縮放大小爲0.33….。
自定義組件和axios與fetch的使用
自定義封裝組件
註冊組件
export default{
   install(Vue){
   Vue.component("my-button",Button);
  }
}
使用組件
import Vue from 'vue';
import Button from '../components/button’
Vue.use(Button)
axios的介紹
axios是一款基於promise封裝的庫,能夠運行在瀏覽器端和node環境中。 vue官方開發組放棄了對其官方庫vue-resource的維護,直接推薦咱們使用axios庫。
 
官方文檔:https://github.com/axios/axios
一、get請求
二、post請求
三、使用URLSearchParams或qs作post提交處理
三、圖片上傳
使用URlSearchParams兼容ie
一、安裝url-search-params-polyfill
npm install url-search-params-polyfill --save
二、入口頁面導入url-search-params-polyfill
import 'url-search-params-polyfill';
fetch的介紹
fetch是ajax2.0,新的瀏覽器如今支持Fetch API,能夠無須其餘庫就能實現Ajax,使用的方式和axios差很少。
瀏覽器兼容性:
桌面瀏覽器
手機、平板電腦
fetch的使用
兼容低版本瀏覽器:https://github.com/github/fetch
安裝:npm install whatwg-fetch --save
引入:import fetch from 'whatwg-fetch'
一、get請求
二、post請求
三、使用URLSearchParams或qs作post提交處理
三、圖片上傳
fetch的get使用
fetch("/api/v1/news",{
   method:"get"
}).then((res)=>{
     return res.json();
}).then(res=>{
    this.newsList=res.data;
});
 
fetch("/proxy/home/user/pwdlogin?token=1ec949a15fb709370f",{
      method:"post",
       headers:{
             'Content-Type':"application/x-www-form-urlencoded"
         }, body:"cellphone="+encodeURIComponent(this.username)+"&password="+encodeURIComponent(this.password)+""
       }).then(res=>res.json()).then(res=>{
        console.log(res);
})
fetch的文件上傳
let data=new FormData();
data.append("headfile",this.$refs["head"].files[0]);
fetch("/proxy/user/myinfo/formdatahead?token=1ec949a15fb709370f",{
       method:"post",
        body:data
}).then(res=>res.json()).then(res=>{
       console.log(res);
});
vue的路由
安裝vue-router
npm install --save vue-router
路由嵌套
{
path:」/goods」,
component: ()=>import(‘./views/goods.vue’),
redirect:’/goods/info’,//頁面重定向
children:[//子路由
  {
      path:」info」,
            component: ()=>import(‘./views/goods_info.vue’);
  }
]
}
]
})
 
 
vue-router的配置
創建一個router.js文件,代碼以下:
import Vue from 'vue';
import Router from 'vue-router';//引用路由
import HomePage from './pages/index';
Vue.use(Router);//裝載路由
//路由實例化
let router=new Router({
    mode:"hash", //一、hash哈希:有#號。二、history歷史:沒有#號
    routes:[
        {
            path:"/",
            name:"index",
            component:HomePage
        },
創建一個router.js文件,代碼以下:
import Vue from 'vue';
import Router from 'vue-router';//引用路由
import HomePage from './pages/index';
Vue.use(Router);//裝載路由
//路由實例化
let router=new Router({
    mode:"hash", //一、hash哈希:有#號。二、history歷史:沒有#號
    routes:[
        {
            path:"/",
            name:"index",
            component:HomePage
        },
  {
            path:'/news',
            name:"news",
            component:()=>import("./pages/news")//路由懶加載
        },
    ]
});
export default router;
動態路由
routes:[
        {
            path: '/news/:id',
            name: 'news',
            component: () => import('./views/News.vue'),
        },
]
<router-link to=「/news/10">新聞頁面</router-link>
 
 
動態路由與接收參數
路由跳轉方式一:
<router-link to=「/about">About</router-link>
路由跳轉方式二:
this.$router.push({path:’/about’})
push進入跳轉歷史記錄
路由跳轉方式三:
this.$router.replace({path:’/about’})
replace不進入跳轉歷史記錄
 
路由傳參方式一:
<router-link to=「/about?id=10">About</router-link>
路由傳參方式二:
this.$router.push({name:’about’,params:{id:10}})
params:參數不顯示url地址上
路由傳參方式三(推薦):
this.$router.push({path:’/about’,query:{id:10}})
query:參數顯示在地址上
 
接收參數方式一:
this.$route.params.id
接收參數方式二(推薦):
this.$route.query.id
返回上一級:
this.$router.go(-1)
路由鉤子函數與路由認證
{
  path:’/user/profile',
  component: ()=>import(‘./user/profile.vue’),
  meta: { title: '我的資料',auth:true }
}
auth:true表示這個頁面須要進行會員認證,auth就是一個標識。
路由守衛
beforeEach:全局前置守衛
const router = new VueRouter({ ... })
router.beforeEach(function (to, from, next) {
    if(to.meta.auth){
      if(Boolean(store.state.isLogin)==true){//已登陸
        next();
      }else{//未登陸
        next({」/login/index"});
      }
    }else{
      next()
    }
});
 
beforeEnter:路由獨享的守衛(路由內鉤子)
const router = new VueRouter({
routes: [
  {
   path: '/foo',
   component: Foo,
   beforeEnter: (to, from, next) => {
         //….
   }
  }
]
})
組件內的守衛-------組件內的鉤子
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應路由被 confirm 前調用
// 不!能!獲取組件實例 `this`
// 由於當守衛執行前,組件實例還沒被建立
},
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,可是該組件被複用時調用
// 舉例來講,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
// 因爲會渲染一樣的 Foo 組件,所以組件實例會被複用。而這個鉤子就會在這個狀況下被調用。
// 能夠訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導航離開該組件的對應路由時調用 // 能夠訪問組件實例 `this`
}
 
應用場景:
組件內的守衛(組件內鉤子)在實際的開發過程當中使用較少, 在實際的項目中beforeRouteLeave還算有用, 使用場景分別爲一下三類狀況:
(一) 清除當前組件中的定時器
當一個組件中有一個定時器時, 在路由進行切換的時候, 可以使用beforeRouteLeave將定時器進行清楚, 以避免佔用內存(能夠用destroyed生命週期鉤子函數代替):
beforeRouteLeave (to, from, next) {
window.clearInterval(this.timer) //清楚定時器
next()
}
 
(二) 當頁面中有未關閉的窗口, 或未保存的內容時, 阻止頁面跳轉
若是頁面內有重要的信息須要用戶保存後才能進行跳轉, 或者有彈出框的狀況. 應該阻止用戶跳轉。
beforeRouteLeave (to, from, next) {
      if (this.isShow){
            alert('必須關閉彈窗才能跳轉頁面');
            next(false);
        } else {
            next();
        }
   }
 
(三) 保存相關內容到Vuex中或Session中
當用戶須要跳轉頁面時, 能夠將公用的信息保存到session或Vuex中(能夠用destroyed生命週期鉤子函數代替)。
beforeRouteLeave (to, from, next) {
  localStorage.setItem(name, content); //保存到localStorage中
  next()
}
history與hash模式的區別
hash模式:路由地址帶#號。適合作後臺管理系統
history模式:路由地址不帶#號。適合作前端宣傳頁面。可是history模式有個問題就是刷新頁面會出現404錯誤,解決方法須要配置服務器。
 
apache解決方案:
在根目錄下新建.htaccess文件,內容以下:
<IfModule mod_rewrite.c>
Options Indexes FollowSymLinks ExecCGI
RewriteEngine On
RewriteBase  /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]   
</IfModule>
 
nginx解決方案:
location  / {
        try_files $uri $uri/ /index.html;
}
Vuex狀態管理
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。將數據分發給各個組件。
應用場景好比:購物車、會員登陸等須要跨頁面,跨組件實時傳遞數據的地方。
安裝vuex
npm install --save vuex
vuex的使用
//導入vuex
import Vuex from 'vuex'
//啓用vuex
Vue.use(Vuex)
//實例化對象
let store=new Vuex.Store({
    state:{}//初始化數據
     mutations:{}//同步操做方法
    actions:{}//異步操做,用於操做mutations裏面的方法,若是mutations裏面的方法操做量大最好寫在actions裏面。   
    getters:{}//有時候咱們須要從 store 中的 state 中派生出一些狀態,例如對列表進行過濾並計數
})
 
new Vue({
  el: '#app',
  router,
  store,//掛載到vue裏使用
  components: { App },
  template: '<App/>'
})
state mutations actions gettters modules的介紹與使用
state:定義vuex的數據源。
state:{
  total:0,
  users:[
    {id:1,name:"張三",age:18},
    {id:2,name:"李四",age:20},
    {id:3,name:"王五",age:22},
    {id:4,name:"趙六",age:25}
  ]
}
 
頁面調用方式一:
this.$store.state.count
頁面調用方式二:
使用輔助函數
import { mapState } from 'vuex'
computed:{
       ...mapState({
         total:state=>state.total
      })
}
 
mutions :同步方式的方法提交,將改變的值賦給state數據源。
mutations:{
  increment(state,payload){
    state.total = payload.count;
  }
}
 
mutions :同步方式的方法提交,將改變的值賦給state數據源。
mutations:{
  increment(state,payload){
    state.total = payload.count;
  }
}
this.$store.commit(「increment」,{count:10});
 
輔助函數提交
import { mapMutations } from 'vuex’
methods: {
     //方式一
    ...mapMutations([
          'increment', // 將 `this.increment()` 映射爲 `this.$store.commit('increment')`
    ]),
   //方式二
    ...mapMutations({
         add: 'increment' // 將 `this.add()` 映射爲 `this.$store.commit('increment')`
    })
  }
 
actions :異步方式的方法提交,用於操做mutions裏面的方法,實際應用裏面獲取ajax異步數據。
actions:{
  inc(conText,payload){
    conText.commit("increment",payload);
  }
}
 
輔助函數提交
import { mapActions } from 'vuex’
methods: {
     //方式一
    ... mapActions ([
          'increment', // 將 `this.increment()` 映射爲 `this.$store.commit('increment')`
    ]),
   //方式二
    ... mapActions ({
         add: 'increment' // 將 `this.add()` 映射爲 `this.$store.commit('increment')`
    })
  }
 
gettters :能夠認爲是 store 的計算屬性,相似於computed,例如對列表進行過濾並計數。
getters:{
  getUsers(state){
    let aUsers=state.users.filter((res)=>{
      return res.age>18;
    })
    return aUsers;
  }
}
this.$store.getters.getUsers
 
輔助函數
import {mapGetters} from 'vuex’
computed: {
//方式一
  ...mapGetters([
    'getUsers'
  ]),
//方式二
...mapGetters({
  getUsers:'getUsers'
})
  }
 
modules: 將 store 分割成模塊(module)。每一個模塊擁有本身的 state、mutation、action、getter。
const moduleA = {
namespaced:true,//命名空間
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}
const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}
 
const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態
熱門的ui庫的使用
自定義指令
// 註冊一個全局自定義指令 `v-focus`
Vue.directive('focus', {
// 當被綁定的元素插入到 DOM 中時……
inserted: function (el) {
// 聚焦元素
  el.focus()
}
})
<input type=「text」 placeholder=「用戶名」 v-focus />
 
// 註冊一個局部指令 `v-position`
directives:{
    position:{
        bind:(el,binding)=>{
            el.style.position="absolute";
            el.style[binding.arg]=binding.value+"px";
        }
    }
}
<div v-position:left="'200'" class="box"></div>
 
鉤子函數
bind:只調用一次,指令第一次綁定到元素時調用。在這裏能夠進行一次性的初始化設置。
 
 
  inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不必定已被插入文檔中)。
 
 
  update:所在組件的 VNode 更新時調用,可是可能發生在其子 VNode 更新以前。指令的值可能發生了改變,也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新 (詳細的鉤子函數參數見下)。
 
鉤子函數參數
name:指令名,不包括 v- 前綴。
binding裏面的參數:
value:指令的綁定值,例如:v-my-directive="1 + 1" 中,綁定值爲 2。
oldValue:指令綁定的前一個值,僅在 update 和 componentUpdated 鉤子中可用。不管值是否改變均可用。
expression:字符串形式的指令表達式。例如 v-my-directive="1 + 1" 中,表達式爲 "1 + 1"。
arg:傳給指令的參數,可選。例如 v-my-directive:foo 中,參數爲 "foo"。
modifiers:一個包含修飾符的對象。例如:v-my-directive.foo.bar 中,修飾符對象爲 { foo: true, bar: true }。
 
Mint-ui官網:http://mint-ui.github.io
Mint-ui介紹: Mint UI 包含豐富的 CSS 和 JS 組件,可以知足平常的移動端開發須要。經過它,能夠快速構建出風格統一的頁面,提高開發效率。
 
Element-ui官網: https://element.eleme.cn
Element-ui介紹:一套爲開發者、設計師和產品經理準備的基於 Vue 2.0 的桌面端組件庫。
Better-Scroll的使用
Better-Scroll官網:http://ustbhuangyi.github.io/better-scroll/doc/api.html
better-scroll 是一款重點解決移動端(已支持 PC)各類滾動場景需求的插件。它的核心是借鑑的 iscroll 的實現。
 
一、實現下拉刷新。
二、實現上拉加載數據
服務器渲染與Nuxt.js
Nuxt.js 是一個基於 Vue.js 的通用應用框架,利用 Vue開發服務端渲染的應用所須要的各類配置。解決vue不支持SEO優化的問題。
 
確保安裝了npx(npx在NPM版本5.2.0默認安裝了):
$ npx create-nuxt-app <項目名>
或者用yarn :
$ yarn create nuxt-app <項目名>
 
head配置:
head: {
title: process.env.npm_package_name || '',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1,maximum-scale=1.0,user-scalable=no' },
{
hid: 'description',
name: 'description',
content: process.env.npm_package_description || ''
},
{
name:"keywords",
content:"大碼女裝,好運買"
},
{
name:"description",
content:"好運買大碼女裝品牌網爲胖mm精選優質大碼女裝品牌旗艦店,是您身邊的專屬衣櫥,介紹各類流行的特大加肥加大時尚大碼女裝品牌,以及韓版大碼女裝,外貿大碼女裝,幫助胖妹妹儘快找到合適的服裝。"
},
{
name:"format-detection",content:"telephone=no,email=no,date=no,address=no"
}
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
//引入手淘flexible.js
script: [{ src: './js/flexible.js', type: 'text/javascript', charset: 'utf-8'}]
},
全局CSS配置:
css: ['element-ui/lib/theme-chalk/index.css','./assets/css/common/public.css']
自定義插件配置:
plugins: [{src:'@/plugins/element-ui',ssr: true},'@/plugins/request'],
全局變量配置:
env: {
//ajax接口地址
baseUrl: process.env.NODE_ENV=='production'?"https://vueshop.glbuys.com/api":"/api",
//根目錄
basePath:"/",
token:"1ec949a15fb709370f"
},
配置代理解決跨域問題:
proxy: {
'/api': {
target: 'https://vueshop.glbuys.com/api', // 目標接口域名
pathRewrite: {
'^/api': '', // 把 /api 替換成 空
changeOrigin: true // 表示是否跨域
}
 
 
}
},
遠程服務器部署上線
阿里雲服務器官網: https://www.alibabacloud.com
阿里雲是阿里巴巴集團(紐交所代碼:BABA)旗下的子公司。經過提供全面完善的全球雲計算服務。
 
nginx下載地址:http://nginx.org/en/download.html
目前最流行最火的web服務器有:Apache、Nginx。
Nginx (engine x) 是一個高性能的HTTP和反向代理web服務器,同時也提供了IMAP/POP3/SMTP服務。
支持:php、nodejs、直播推流等。
使用nginx配置代理exproess服務器
一、啓動express服務器
supervisor app.js
http://localhost:300
二、nginx配置反向代理
打開nginx.conf
 
 
 
 
server {
   listen       1920;
   server_name  localhost;
 
 
   location / {
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host  $http_host;
       proxy_set_header X-Nginx-Proxy true;
       proxy_set_header Connection "";
       proxy_pass      http://localhost:3003;
   }
}
相關文章
相關標籤/搜索