初来乍到-Vue+Vant+Vuex+Vue-router+less实现公司需求(一):换肤

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

 

  欢迎你们来到技术宝的掘金世界,您的star是我写文章最大的动力!GitHub地址     
  这是一篇使用vue+vant+vuex+vue-router实现公司需求的文章,会详细的介绍每一个插件的做用等...   
   感受不错的小伙伴,点赞star走一波;  
   感受文章有误的小伙伴,评论区、QQ群走一波;  
   虚心求教,不胜感激~html

开篇题外话:前端

 因为技术宝刚到公司,人生地不熟,正式项目尚未启动,暂时负责修改样式,解决同事遇到的技术小bug...,可是今天我接到了个人直接领导给我安排的任务,心情异常激动,说是让准备如下几个功能:vue

开篇点题:   node

1.换肤react

2.动效webpack

3.div换位置(动态换)(手动换)git

 今天就来带领你们来跟技术宝一块儿来学习下这些内容!github

1、项目搭建

 首先开始页面的开发,了解前端的人都知道,没有项目怎么开始写页面呢?因此咱们接下来的任务就是搭建项目!首先将上次咱们用webpack4搭建的Vue项目搭建起来,这里我给你们准备了Github地址Webpack4OfVue,你们记得给我点个star哦,不胜感激!web

1.下载项目

 和使用Npm同样,咱们首先确保本身电脑上安装了node,肯定能够执行git相关的命令,首先git clone项目到本地,以下图:

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
复制代码

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.
复制代码

2、项目页面编写

 在上一节中咱们搭建好了基本的开发环境,接下来就带你们编写基本的页面,因为样式不在此篇文章的考虑范围以内,因此咱们直接采用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内容
复制代码

项目骨架以下图

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>
复制代码

运行项目你会发现经过对应路径已经有页面展现出来

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的内容(只关注样式部分,逻辑部分能够暂时忽略)
复制代码

效果图以下(很丑,粗略设计):

 接下来我就经过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位置,但愿你们能够期待哦!

若是你以为个人文章还不错的话,能够给个star哦~,GitHub地址

相关文章
相关标签/搜索