上文中说到了利用Element-ui优化了导航栏,本节介绍抽离公共的less变量与利用Element-Ui实现登录注册页面。本项目git地址:
https://gitee.com/vuejslearn/news-list.git
抽离less,引入公共less变量
我们的样式代码采用了less语法,因此很多地方可以封装出一些共性的代码。比如布局上,本项目的布局采用了flex布局。截止目前,我们发现页面中的样式代码有很多相同的flex布局代码:
.flex-display (@dir: column, @content: center, @align: center) { display: flex; flex-direction: @dir; justify-content: @content; align-items: @align;}
如果把这些代码抽离出一个公共的文件,那么对于我们开发速度就会提高很多。那么如何抽离呢?
很简单,首先我们需要安装style-resources-loader插件:
npm install style-resources-loader --save
这个插件是用来帮助我们注入公共的样式文件,导入css / sass / scss / less / stylus这些内容,这样可以避免我们在每个文件里使用import导入。安装完后,我们在vue.config.js中添加对样式文件的导入。
首先在最上面引入path:
// 配置全局less变量 chainWebpack: config => { const types = ['vue-modules', 'vue', 'normal-modules', 'normal'] types.forEach(type => addStyleResource(config.module.rule('less').oneOf(type))) }, css: { loaderOptions: { less: { javascriptEnabled: true } } }
在module.exports里我们加入:
// 配置全局less变量 chainWebpack: config => { const types = ['vue-modules', 'vue', 'normal-modules', 'normal'] types.forEach(type => addStyleResource(config.module.rule('less').oneOf(type))) }, css: { loaderOptions: { less: { javascriptEnabled: true } } }
然后在module.exports后面,我们加入方法:
function addStyleResource (rule) { rule.use('style-resource') .loader('style-resources-loader') .options({ patterns: [ // 需要全局导入的less路径,自己修改 path.resolve(__dirname, './src/assets/styles/global.less') ] })}
ok,配置文件写好后,我们在上面配置的路径里(src/assets/styles),添加配置文件global.less,文件内容就是开头的公共方法:
至此,公共的less抽离完成。我们在一般的页面的使用方法和以前一样,没有任何变化,无需单独引入这个样式文件即可使用。
Vuex持久化
vuex很好用,可以帮助我们记录组件状态,并且是响应式的。但是有个问题,就是它的状态是保存在内存里的,当我们的浏览器刷新后,状态就重新初始化了。比如目前我们的代码中对登录状态的记录,就是。登陆后,我们再刷新浏览器,发现有标记为未登录,这显然不对。有没有一种可能,将我们的状态记录到本地,然后刷新后重新获取呢?这样就不怕刷新了。答案是有的。很简单,我们利用sessionStorage即可实现,那为什么不用localStorage呢?因为前者是会话存储,后者是本地存储,前者当页面关闭后会自动清除,后者不会。
因此我们保持登录状态最好用前者。浏览器退出,或者关闭页面,自动退出登录,比较好。
那具体怎么做呢?很简单我们只要在组件创建后,监听刷新事件,当刷新前,我们持久化状态到本地,然后刷新完,组件重新创建,再把值从本地合并到vuex里。
但是我们想让全局的组件都会这样,那怎么办呢?很简单,我们只需要在app中执行上面的步骤就可以了。
编辑App.vue,添加代码:
created () { // 在页面加载时读取sessionStorage里的状态信息 if (sessionStorage.getItem('store')) { this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store')))) } // 在页面刷新时将vuex里的信息保存到sessionStorage里 window.addEventListener('beforeunload', () => { sessionStorage.setItem('store', JSON.stringify(this.$store.state)) }) }
这样,在刷新时,就可以自动的同步数据了。
Vuex多模块构建
目前的vuex是一个模块的,如果我们的应用比较大,把所有的状态都写在这个文件里,那样会越来越臃肿。我们可以按照页面、组件来分模块进行管理。然后都集成到vuex中即可。目前我们只有一个登录页,因此我们创建一个登陆模块,来保存登陆的状态。
在store中,新建modules文件夹,进入后再创建login文件夹,进入后创建index.js。这个文件用来管理登陆页的状态,把之前store/index.js的登录状态移动到这里:
login/index.js
导出这些:
然后,我们去掉store/index.js中原有的登录状态的代码,精简后:
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({ modules: { })
ok,我们引入之前login的模块,并加入到modules中:
import Vue from 'vue'import Vuex from 'vuex'import login from './modules/login'Vue.use(Vuex)export default new Vuex.Store({ modules: { login }})
这样,我们就成功地分了模块管理了。但是,我们仔细看,在login/index.js中,我们加了一句话:
namespaced: true,
这是什么意思呢?这意思是,我们在每个模块里,使用了命名空间,使用了命名空间,我们的模块就拥有了自己的action、mutation 和 getter 。如果没有,那么我们每建立一个模块,它的mutation等会注册到全局命名空间,这样其他模块,都能随便的对这个mutation做操作。有了命名空间,模块会更加的封闭,同时避免了冲突。
改变了vuex的多模块模式后,我们对登录状态的操作就发生了变化。比如,我们用getters读取login的状态时,语句变成了:
this.$store.getters['login/login']
同时,我们也可以用mapGetters来简化我们的操作:
import { mapGetters } from 'vuex'....computed: { ...mapGetters({ logined: 'login/login' }) },
这样两种方法,我们获取到了某个模块下的状态。同理,更改状态的语句变成:
this.$store.dispatch('login/login')
以上的路径,均是命名空间+对应的getters或者mulation。
以上就是vuex的模块化管理,下篇文章我们将继续在此基础上,实现我们的登录注册页面,同时优化登录与非登陆状态下路由的跳转。先看一看登录、注册完成后的样子吧!
注册页面
登录页面
朋友们也可以直接下载代码运行,可以看到上面的页面。
原创不容易,鉴于本人水平有限,文中如有错误之处欢迎大家指正。以后我会持续发布vue实战系列的文章,喜欢的朋友欢迎关注。