初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

安穩.發表於2019-03-11

Created By JishuBao on 2019-03-11 12:38:22
Recently revised in 2019-03-13 12:38:22

 

  歡迎大家來到技術寶的掘金世界,您的star是我寫文章最大的動力!GitHub地址     
  這是一篇使用vue+vant+vuex+vue-router實現公司需求的文章,會詳細的介紹每個外掛的作用等...   
   感覺不錯的小夥伴,點贊star走一波;  
   感覺文章有誤的小夥伴,評論區、QQ群走一波;  
   虛心求教,不勝感激~

開篇題外話:

 由於技術寶剛到公司,人生地不熟,正式專案還沒有啟動,暫時負責修改樣式,解決同事遇到的技術小bug...,但是今天我接到了我的直接領導給我安排的任務,心情異常激動,說是讓準備以下幾個功能:

開篇點題:   

1.換膚

2.動效

3.div換位置(動態換)(手動換)

 今天就來帶領大家來跟技術寶一起來學習下這些內容!

一、專案搭建

 首先開始頁面的開發,瞭解前端的人都知道,沒有專案怎麼開始寫頁面呢?所以我們接下來的任務就是搭建專案!首先將上次我們用webpack4搭建的Vue專案搭建起來,這裡我給大家準備了Github地址Webpack4OfVue,大家記得給我點個star哦,不勝感激!

1.下載專案

 和使用Npm一樣,我們首先確保自己電腦上安裝了node,確定可以執行git相關的命令,首先git clone專案到本地,如下圖:

初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

2.跑起來

 和正常的vue/react專案一樣,在檔案下執行 yarn install/npm install && yarn start/npm start 執行專案並開啟http://localhost:10000即可看到

$ yarn install
yarn install v1.7.0
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.2.7: The platform "win32" is incompatible with this module.
info "fsevents@1.2.7" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > less-loader@4.1.0" has unmet peer dependency "less@^2.3.1 || ^3.0.0".
[4/4] Building fresh packages...
success Saved lockfile.
Done in 123.95s.
複製程式碼
$ yarn start
yarn run v1.7.0
$ cross-env webpack-dev-server --config build/webpack.dev.conf.js
 98% after emitting DONE  Compiled successfully in 3639ms10:43:15

 I  You application is running here http://localhost:10000

 N  Some additionnal notes to be displayed unpon successful compilation
複製程式碼

初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

3.安裝demo所需依賴

 由於此次demo的開發需要依賴於Vant+Vuex+Vue-router+less,所以我們要安裝所需的依賴!

 執行命令:

yarn add vuex vue-router vant
複製程式碼

 安裝所需依賴完畢!

yarn add v1.7.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.2.7: The platform "win32" is incompatible with this module.
info "fsevents@1.2.7" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > less-loader@4.1.0" has unmet peer dependency "less@^2.3.1 || ^3.0.0".
[4/4] Building fresh packages...

success Saved lockfile.
warning Your current version of Yarn is out of date. The latest version is "1.13.0", while you're on "1.7.0".
info To upgrade, run the following command:
$ curl --compressed -o- -L https://yarnpkg.com/install.sh | bash
success Saved 7 new dependencies.
info Direct dependencies
├─ vant@1.5.9
├─ vue-router@3.0.2
└─ vuex@3.1.0
info All dependencies
├─ @babel/runtime@7.3.4
├─ @vant/icons@1.0.8
├─ @vue/babel-helper-vue-jsx-merge-props@1.0.0-beta.2
├─ vant@1.5.9
├─ vue-lazyload@1.2.3
├─ vue-router@3.0.2
└─ vuex@3.1.0
Done in 24.50s.
複製程式碼

二、專案頁面編寫

 在上一節中我們搭建好了基本的開發環境,接下來就帶大家編寫基本的頁面,由於樣式不在此篇文章的考慮範圍之內,所以我們直接採用vant的ui框架進行頁面的搭建!

1.新建模糊頁面login、home、secord

 本文是移動端的一個編寫,所以我們採用有讚的vant來編寫專案,在src資料夾下新建一個views資料夾,再在views資料夾下新建幾個基本頁面內容如下:

<template>
    <div class="container">login</div>
</template>

<script>
export default{
    
}
</script>

<style>
.container{
    background-color:skyblue;
    font-size:20px;
}
</style>
//login.vue檔案內容
複製程式碼
<template>
    <div class="container">home</div>
</template>

<script>
export default{
    
}
</script>

<style>
.container{
    background-color:skyblue;
    font-size:20px;
}
</style>
//home.vue檔案內容
複製程式碼
<template>
    <div class="container">secord</div>
</template>

<script>
export default{
    
}
</script>

<style>
.container{
    background-color:skyblue;
    font-size:20px;
}
</style>
//secord.vue內容
複製程式碼

專案骨架如下圖

初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

2.新建路由配置檔案

 在src資料夾下新建router資料夾,資料夾下新建index.js檔案當作路由配置檔案

import Vue from 'vue';
import VueRouter from 'vue-router';

import Home from './../views/home';
import Secord from './../views/secord';
import UserLogin from './../views/login';

import globalStore from './../store/global';

Vue.use(VueRouter);

const router=new VueRouter({
    routes:[
        {
            path:'/',
            redirect:to=>{
                if(localStorage.getItem('token') && globalStore.state.isAuthentication){
                    return {path:'/home'}
                }else{
                    return {path:'/user/login'}
                }
            }//  /路徑下如果持久化儲存localStorage下有token並且global.js下的Authentication(是否登陸)為true/false,如果登陸跳轉到Home頁面,沒有的話,就跳轉到使用者登陸頁面。
        },
        {
            path:'/user/login',
            name:'userlogin',
            component:UserLogin
        },
        {
            path:'/effects',
            name:'effects',
            component:Effects,
        },
        {
            path:'/home',
            name:'home',
            component:Home,
        },
        {
            path:'/secord',
            name:'secord',
            component:Secord
        }
    ]
});

export default router;
//index.js檔案內容如上!
複製程式碼

3.小試牛刀

import Vue from 'vue';//在import Vue的過程中,Vue主要是在原型上完成方法的掛載,並且初始化了全域性的API。
import App from './App.vue';//引入主VUE頁面
import router from './router/index';

import './styles/reset.css' /**引入樣式重置 */

Vue.config.productionTip = false;//阻止啟動生產訊息,常用作指令

new Vue({
    el:"#root",//將渲染結果掛在這id為root的html上
    router,
    render:h=>h(App),//render函式是渲染一個檢視,然後提供給el掛載,如果沒有render那頁面什麼都不會出來
});
//index.js檔案內容如上!
複製程式碼

在src資料夾下的index.js下引入路由配置檔案,如上程式碼所示

同時修改app.vue(根vue頁面)的template標籤

<template>
    <div id="app">
        <router-view />
    </div>
</template>
複製程式碼

執行專案你會發現通過對應路徑已經有頁面展示出來

初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

4.rem實現手機端自適應

 因為本文是基於手機端的小demo,所以需要實現手機端螢幕大小自適應!

rem佈局的本質是等比縮放,rem是根據根font-size的大小設定的

 在src資料夾下新建utils,用來存放工具類函式等...

 在utils資料夾下新建Rem.js

const baseSize=32;

function setRem(){
    const htmlWidth=document.documentElement.clientWidth || document.body.clientWidth;
    const htmlDom=document.getElementsByTagName('html')[0];
    //設定頁面根節點字型大小
    htmlDom.style.fontSize=htmlWidth/10+'px';
}

setRem();
//Rem.js內容如上
複製程式碼

然後在src資料夾的index.js檔案中新增rem設定,即引入

import './styles/reset.css' /**引入樣式重置 */
複製程式碼

因為暫時沒有在less中發現和scss中類似的寫法,故在scss定義一個px轉化為rem的方法,在styles資料夾新建common.scss,需要時引入就行

@function pxToRem($px){
    @return $px/20px*1rem;
}
//common.scss內容如下
複製程式碼

5.在專案中引入vuex

 雖然我們們只有幾個頁面,完全沒必要引入vuex,使專案看起來變得很複雜,但是這不是為了讓大家熟悉vuex嘛,知道如何在專案中使用,首先在src選新建store資料夾,暫且定義三個檔案,global.js存放與全域性相關的狀態,home.js存放home頁面相關的狀態,secord.js存放secord頁面相關的狀態。

import Vue from 'vue';
import Vuex from 'vuex';

import home from './home';
import secord from './secord';

Vue.use(Vuex);

export default new Vuex.Store({
    namespaced:true,

    modules:{
        home,
        secord
    },

    state:{
        isAuthentication:false,//是否有許可權,是否登陸
    },
    getters:{

    },
    actions:{

    },
    mutations:{
        updateState(state,payload){
            Object.assign(state,payload);
        }
    }
});
//global.js檔案內容如上
複製程式碼
export default {

    namespaced:true,

    state:{

    },
    getters:{

    },
    actions:{

    },
    mutations:{
        updateState(state,paylaod){
            Object.assign(state,payload);
        }
    }

}
//home.js內容如上
複製程式碼
export default {

    namespaced:true,

    state:{

    },
    getters:{

    },
    actions:{

    },
    mutations:{
        updateState(state,paylaod){
            Object.assign(state,payload);
        }
    }

}
//secord.js內容如上
複製程式碼

檔案寫好後可以在index.js裡面引入相關的檔案使之初始化

import store from './store/global';

new Vue({
    el:"#root",//將渲染結果掛在這id為root的html上
    router,
    store,//載入vuex
    render:h=>h(App),//render函式是渲染一個檢視,然後提供給el掛載,如果沒有render那頁面什麼都不會出來
});
複製程式碼

vuex核心概念

1.namespaced:也就是識別符號,指明在哪個模組之後,vuex中的store分模組管理,需要在store的index.js中引入各個模組,為了解決不同模組命名衝突的問題,將不同模組的namespaced:true,之後在不同頁面中引入getter、actions、mutations時,需要加上所屬的模組名。

2.modules:Modules:將store分割成不同的模組。

3.state:包含所有應用級別狀態的物件。

4.getters: vuex 中的getters 想當於vue中的computed ,getters是vuex 中的計算屬性 ,計算屬性寫起來是方法,但它是個屬性。

5.actions:包含非同步操作、提交mutaions改變狀態。

6.mutations:唯一修改狀態的事件的回撥函式。

因為我們暫時沒有進行業務模組的開發,所以暫時沒有定義很多狀態等...

6.登陸頁面login.vue的佈局樣式編寫

 在閱讀了Vant的官網後,我們需要現在public資料夾下的index.html檔案的head標籤內部引入vant樣式!

 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@1.6/lib/index.css">
複製程式碼

 在專案中引入babel-plugin-import

PS E:\MyProject\Webpack4OfVueStage> yarn add babel-plugin-import -D
yarn add v1.7.0
[1/4] Resolving packages...
[2/4] Fetching packages...
info fsevents@1.2.7: The platform "win32" is incompatible with this module.
info "fsevents@1.2.7" is an optional dependency and failed compatibility check. Excluding it from installation.
[3/4] Linking dependencies...
warning " > less-loader@4.1.0" has unmet peer dependency "less@^2.3.1 || ^3.0.0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ babel-plugin-import@1.11.0
info All dependencies
└─ babel-plugin-import@1.11.0
Done in 7.72s.
複製程式碼

因為專案中使用的是babel7,所以新建babel.config.js

//在編譯過程中將import的寫法自動轉換為按需引入的方式
module.exports={
    plugins:[
        [
            'import',{
                libraryName:'vant',
                libraryDirectory:'es',
                style:true
            },'vant'
        ]
    ]
}
複製程式碼

在index.js檔案裡面引入所需的大部分元件

import {Dialog,Row,Col,Picker,Field,Cell,CellGroup,Button,Toast,NavBar,Tabbar,TabbarItem,List,Panel,NoticeBar,Tag,Popup} from 'vant';

Vue.use(Row).use(Col);
Vue.use(Field);
Vue.use(Cell).use(CellGroup);
Vue.use(Button);
Vue.use(Toast);
Vue.use(NavBar);
Vue.use(Tabbar).use(TabbarItem);
Vue.use(Panel);
Vue.use(List);
Vue.use(NoticeBar);
Vue.use(Tag);
Vue.use(CircleButton);
Vue.use(Popup);
Vue.use(Picker);
Vue.use(Dialog);
複製程式碼
<template>
    <div class="change" >
        <div style="width:100%;height:150px;"></div>
        <div style="margin-top:20px">
        <van-row type="flex" justify="center">
            <van-col span="20">
                <van-cell-group style="border-radius:10px;">
                    <van-field 
                        v-model="username"
                        required 
                        clearable
                        label="使用者名稱"
                        icon="question"
                        placeholder="請輸入使用者名稱"
                        
                    />

                    <van-field 
                        v-model="password"
                        type="password"
                        label="密碼"
                        placeholder="請輸入密碼"
                        required 
                        v-on:keyup.13="handleLogin"
                    />    
                </van-cell-group>
            </van-col>
        </van-row>
        </div>
        <div style="margin-top:180px">
        <van-row type="flex" justify="center">
            <van-col span="18">
                <van-button type="primary" size="large" @click="handleLogin">確定</van-button>
            </van-col>
        </van-row>
        </div>
         
    </div>
</template>

<script>
    
    import { mapState } from 'vuex';
    export default{
        data(){
            return{
                password:'',
                username:'',
            }
        },
        computed:{
            ...mapState({
                isAuthentication:state=>state.isAuthentication,
            })
        },
        methods:{
            handleLogin(){
                if(!this.username || !this.password){
                    this.$toast({
                        message:'請將資訊填寫完整'
                    });
                }else{
                    this.$store.dispatch('login',{
                        password:this.password,
                        username:this.username,
                    });
                    this.$router.push({name:'home'})
                }   
            }
        },
    }
</script>

<style lang="less" scoped>
    @import "./../styles/color.less";
    .change{
        width:100%;
        height:100%;
        z-index:2;
        position:absolute;
        top:0;
        bottom:0;
    }
    
</style>
//以上為login.vue的內容(只關注樣式部分,邏輯部分可以暫時忽略)
複製程式碼

效果圖如下(很醜,粗略設計):

初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

 接下來我就通過login.vue檔案帶領大家領略vuex的用法

<van-col span="18">
    <van-button type="primary" size="large" @click="handleLogin">確定</van-button>
</van-col>
複製程式碼

 通過vue的**@click繫結一個點選事件handleLogin**,在methods裡面定義一個方法handleLogin

handleLogin(){
                if(!this.username || !this.password){
                    this.$toast({
                        message:'請將資訊填寫完整'
                    });
                }else{
                    this.$store.dispatch('login',{
                        password:this.password,
                        username:this.username,
                    });
                    this.$router.push({name:'home'})
                }   
}
複製程式碼

 輸入框輸入賬號密碼,通過v-model指令將輸入框的內容與data裡面定義的usernamepassword繫結,當賬號為空或者密碼為空時,呼叫vanttoast(彈出框:將資訊填寫完整),當賬號密碼都不為空時,通過this.$store.dispatch請求login方法,值得注意的是dispatch觸發的是vuex模組的actions(常用於非同步操作),讓我們看看globalactions中的login方法,localStorage是一種瀏覽器儲存資料的方式。

 async login({commit},payload){
            if(payload.password && payload.username){
                localStorage.setItem('token','AUTHENTION');
                commit('updateState',{
                    isAuthentication:true
                })
            }else{

            }
}
複製程式碼

 當賬號密碼存在時,commit觸發updateState方法,值得注意的是commit提交觸發的是mutations方法:

updateState(state,payload){
            Object.assign(state,payload);
}
複製程式碼

Object.assign()方法用於將多個物件合併為一個物件,上面的updateState方法可以將isAuthentication設定為true。

import Vue from 'vue';
import Vuex from 'vuex';

import home from './home';
import secord from './secord';

Vue.use(Vuex);

export default new Vuex.Store({
    namespaced:true,

    modules:{
        home,
        secord
    },

    state:{
        isAuthentication:false,
    },
    getters:{

    },
    actions:{
        async login({commit},payload){
            if(payload.password && payload.username){
                localStorage.setItem('token','AUTHENTION');
                commit('updateState',{
                    isAuthentication:true
                })
            }else{

            }
        }
    },
    mutations:{
        updateState(state,payload){
            Object.assign(state,payload);
        }
    }
});
//global.js完整程式碼
複製程式碼

7.home頁面(換膚)的編寫

 由上面的login.vue所寫,當填寫賬號密碼後:

this.$router.push({name:'home'})
複製程式碼

 這是vue-router的方法,目的是跳轉到home頁面,此時url為home

 話不多說,先把程式碼展示出來,再展示邏輯部分。

<template>
    <div class="home">
        <van-nav-bar
            title="測試換膚功能"
            left-text="返回"
            left-arrow
            right-text="換膚"
            class="change"
            @click-right="changeSkin"
        ></van-nav-bar>

        <van-card
            num="2"
            price="2.00"
            desc="描述資訊"  
            title="商品標題"
            :thumb="imageUrl"
        />
        <van-card
            num="2"
            price="2.00"
            desc="描述資訊"  
            title="商品標題"
            :thumb="imageUrl"
        />
        <van-card
            num="2"
            price="2.00"
            desc="描述資訊"  
            title="商品標題"
            :thumb="imageUrl"
        />
        <van-card
            num="2"
            price="2.00"
            desc="描述資訊"  
            title="商品標題"
            :thumb="imageUrl"
        />
        <van-card
            num="2"
            price="2.00"
            desc="描述資訊"  
            title="商品標題"
            :thumb="imageUrl"
        />

        <van-popup v-model="formVisible" position="bottom">
            <van-picker 
                show-toolbar
                title="請選擇皮膚"
                @cancel="handleCancelSelect"
                @confirm="handleSubmitSelect"
                :columns="columns"  
            />
        </van-popup>

        <common-tabbar 
            :activeIndex="activeIndex"
            v-on:onChange="handleChangeTabBar" 
        />
    </div>
</template>

<script>

import CommonTabbar from './../components/common/Tabbar.vue';
import SkinTypeEnum from './../enum/SkinTypeEnum';
import { mapState } from 'vuex';

export default{
    data(){
        return{
            show:true,
            activeIndex:0,
            imageUrl:'http://img5.mtime.cn/CMS/News/2019/03/11/091140.35777532_620X620.jpg',
            columns: [`少女粉`,
                    `天空藍`, 
                    `茄子紫`, 
                    `清新綠`,
                    `警告色`,
                    `危險紅`
            ]
        }
    },
    components:{
        CommonTabbar
    },
    computed:mapState({
        formVisible:state=>state.home.formVisible,
    }),
    methods:{
        handleChangeTabBar(e){
            console.log(e);
            if(e===2){
                this.$router.push({name:'secord'})
            }else if(e===1){
                this.$router.push({name:'effects'})
            }
        },
        changeSkin(){//點選換膚彈出皮膚選擇框
            this.$store.commit('home/updateState',{
                formVisible:true
            })
        },
        handleCancelSelect(){//點選取消
            this.$store.commit('home/updateState',{
                formVisible:false,
            })
        },
        handleSubmitSelect(value,index){//點選確定
            let colorValue=SkinTypeEnum.getThemeValue(value);
            document.getElementById('app').className=`${colorValue}Theme`;
            this.$store.commit('home/updateState',{
                formVisible:false,
            });
            localStorage.setItem('app_theme',document.getElementById('app').className)
        }
    }
}
</script>

<style scoped lang="less">
@import "./../styles/color.less";
.change{
     /deep/.van-icon .van-icon-arrow-left .van-nav-bar__arrow{
         color:white;
     }
     /deep/.van-nav-bar__text{
         color:white;
     }
     /deep/.van-nav-bar__title{
         color:white;
     }
}
</style>
//home.vue的內容
複製程式碼

其中我們自定義了一個元件tabbar,因為元件中每個頁面都用到了這個元件,所以我們把它抽象成一個元件,這樣我們就不需要重複寫程式碼了,每個頁面直接引用就可以了,當然頁面也不是很多,我們完全可以每個頁面都寫一個,但是這不是為了讓大家都瞭解元件的用法嘛!!!

 新建components資料夾,在components資料夾下新建common資料夾,在common資料夾下新建Tabbar.vue檔案。

<template>
    <van-tabbar v-model="activeIndexData" class="change" @change="handleChangeTabBar">
        <van-tabbar-item>
                <span>換膚</span>
                <i slot="icon" class="iconfont iconhuanfu" style="{fontSize:'20px',color:'white'}"></i>
        </van-tabbar-item>
        <van-tabbar-item>
                <span>動效</span>
                <i slot="icon" class="iconfont iconxiaoguo" style="{fontSize:'20px'}"></i>
        </van-tabbar-item>
        <van-tabbar-item>
                <span>切換</span>
                <i slot="icon" class="iconfont iconqiehuan" style="{fontSize:'20px'}"></i>
        </van-tabbar-item>
    </van-tabbar>
</template>

<script>
export default{
    data(){
        let me=this;
        return{
            activeIndexData:me.activeIndex,
        }
    },
    methods:{
        handleChangeTabBar(e){
            this.$emit('onChange',e)
        }
    },
    props:{
        activeIndex:{
            type:Number,
            default:0,
        },
    },
}
</script>

<style lang="less">
@import "./../../styles/color.less";
.change{
    /deep/.van-tabbar-item{
        color:white;
    }
    /deep/.van-tabbar-item--active{
        color:#1989fa;
    }
}

</style>
//tabbar.vue的內容
複製程式碼

 其中props定義的是父元件傳來的值,型別是number,預設值是0。

引入元件並註冊元件

 components:{
        CommonTabbar
},
複製程式碼

computed中可以獲取vuex home模組定義的state

computed:mapState({
        formVisible:state=>state.home.formVisible,
}),
複製程式碼

 當點選換膚的時候,觸發changeSkin方法:

changeSkin(){//點選換膚彈出皮膚選擇框
            this.$store.commit('home/updateState',{
                formVisible:true
            })
},
複製程式碼

 觸發commit,即home模組裡面的mutations裡面的updateState方法,使formVisible設定為true,formVisible與v-model繫結,通過true/false來控制popup顯示/隱藏。

 點選換膚讓popup彈窗顯示出來,popup裡面有picker的column繫結了columns,即各種皮膚顏色。

<van-popup v-model="formVisible" position="bottom">
            <van-picker 
                show-toolbar
                title="請選擇皮膚"
                @cancel="handleCancelSelect"
                @confirm="handleSubmitSelect"
                :columns="columns"  
            />
</van-popup>
複製程式碼

 當點選取消時設定formVisible為false時,彈框即消失。

 當點選確定選擇顏色時,觸發handleSubmitSelect方法,此時我再此介紹一個列舉類形式的函式,此函式的目的是通過一個英文值含義或者中文值含義來返回對應的值。

function getThemeValue(value){

    console.log('a');

    if(!value){
        return '';
    }

    if(value === "少女粉"){
        return 'girl';
    }

    if(value === "天空藍"){
        return 'blue';
    }

    if(value === "茄子紫"){
        return 'purple';
    }

    if(value === '清新綠'){
        return 'green';
    }

    if(value === '警告色'){
        return 'warning';
    }

    if(value === '危險紅'){
        return 'danger';
    }

}

export default {
    getThemeValue,
}
//SkinTypeEnum.js定義
複製程式碼

 直接引入呼叫,把中文值轉化為對應的英文。

handleSubmitSelect(value,index){//點選確定
            let colorValue=SkinTypeEnum.getThemeValue(value);
            document.getElementById('app').className=`${colorValue}Theme`;
            this.$store.commit('home/updateState',{
                formVisible:false,
            });
            localStorage.setItem('app_theme',document.getElementById('app').className)
}
//改變膚色的重要方法
複製程式碼

接下來就是整個功能的重中之重了!!請祥聽

8.編寫less檔案實現換膚

1.在styles資料夾下新建theme.less

.theme(@background){
    .change{
        background-color:@background;
    }
}
//theme.less內容
複製程式碼

2.在styles資料夾下新建color.less

@import "./theme.less";

@girlPink:#FC9F9F;//少女粉
@skyBlue:#1890FF;//天空藍
@eggplantPurple:purple;//茄子紫
@freshGreen:#09C160;//清新綠
@warningColor:#FF976A;
@dangerRed:#FF4D4F;//危險紅


.girlTheme{
    .theme(@girlPink);
}
.blueTheme{
    .theme(@skyBlue);
}
.purpleTheme{
    .theme(@eggplantPurple);
}
.greenTheme{
    .theme(@freshGreen);
}
.warningTheme{
    .theme(@warningColor);
}
.dangerTheme{
    .theme(@dangerRed);
}
//color.less內容
複製程式碼

熟悉Less的小夥伴們應該看到以後就大致明白了,通過color.less引入theme.less,可以使change類名下的背景顏色改為相對應類目不一樣的顏色

3.在需要改變膚色的頁面引入color.less,並將需要修改的div類目設定為change

 因為我們的專案是單頁(SPA)應用,所有的vue頁面都是在根div下,所以設定根目錄下的class類名就可以改變vue頁面class類名change的div背景色。所以我們把想要更換div背景色套上change類名就行了!其實我們之前寫的頁面都已經套上change了哦!不知道大家有沒有發現!

4.持久化改變膚色

 其實這裡還是有一個Bug的,就是每當重啟服務瀏覽器的時候,所有的類名初始化,之前的顏色將會消失,所以我們這裡將皮膚主題儲存進localStorage(如果不手動清楚瀏覽器快取,它就始終不會消失!)

localStorage.setItem('app_theme',document.getElementById('app').className)
複製程式碼

在根vue app.vue裡面的生命週期函式中設定存下來的膚色,一切萬事OK!

<template>
    <div id="app">
 
        <router-view />
   
    </div>
</template>

<script>
export default {
    data(){
        return{
            msg:'webpack4搭建react環境基本完成,是不是很簡單呢'
        }
    },
    mounted:function(){
        let theme=localStorage.getItem('app_theme');
        document.getElementById('app').className=theme;
    }
}
</script>
複製程式碼

大致效果就如下圖所示,下一個需求是動態更改div位置,希望大家可以期待哦!

初來乍到-Vue+Vant+Vuex+Vue-router+less實現公司需求(一):換膚

如果你覺得我的文章還不錯的話,可以給個star哦~,GitHub地址

相關文章