使用normalize.scss
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
路由
获取路由列表
使用elementui
全局样式表
elementui.scss:部分样式需要进行全局修改
全局组件
两种模式
compiler
runtime(默认)
修改指向文件,指向vue/dist/vue.js
config.resolve.alias.set('vue', 'vue/dist/vue.esm.js')
定义全局组件
在src目录下建立icons文件夹,建立index.js文件,在其中定义组件,再引入到main.js中,最后把花括号里面的内容抽离到一个vue文件中
index:
import Vue from 'vue'
import Svgicon from './Svgicon.vue'
Vue.component('svg-icon', Svgicon)
/**
* require.context('./svg', false, /\.svg$/)参数:
* 第一:目录
* 第二:是否遍历子级目录
* 第三:定义遍历文件规则
*/
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => {
return requireContext.keys().map(requireContext)
}
requireAll(req)
Svgicon:
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName"></use>
</svg>
</template>
<script>
import {reactive, ref, isRef, toRefs, onMounted, computed } from '@vue/composition-api'
export default {
name: 'svgIcon',
//接受父组件传值
props: {
iconClass: {
type: String,
defauot: ''
},
className: {
type: String,
defauot: ''
}
},
setup (props) {
console.log(props.iconClass)
const msg = ref('svgIcon')
// computed监听
const iconName = computed(() => `#icon-${props.iconClass}`)
const svgClass = computed(() => {
if (props.className) {
return `svg-icon ${props.className}`
} else {
return 'svg-icon'
}
})
return {
msg,
iconName, svgClass
}
}
}
</script>
<style lang="scss" scoped>
</style>
svg文件
在模板引入:
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="name"></use>
</svg>
解析文件:
/**
* require.context('./svg', false, /\.svg$/)参数:
* 第一:目录
* 第二:是否遍历子级目录
* 第三:定义遍历文件规则
*/
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => {
return requireContext.keys().map(requireContext)
}
requireAll(req)
在vue.config.js中依赖
chainWebpack:config => {
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]',
include: ['./src/icons']
})
}
修改color的时候要使用fill
在router的meta对象中传入icon属性,在获取路由列表的时候获取该属性,并渲染到svg-icon组件中
//路由:
const routes = [
{
path: '/',
redirect: 'login',
hidden: true,
meta: {
name: '首页'
}
},
{
path: '/login',
name: 'Login',
hidden: true,
meta: {
name: '登录',
icon: 'login'
},
component: () => import('../views/Login/index.vue')
}
]
结合ElementUI菜单,获取路由列表,渲染导航
<template v-for="(routeItem,index) in routeList" >
<el-submenu :key="routeItem.id" :index="routeItem.path" v-if="!routeItem.hidden">
<!-- 一级菜单 -->
<template slot="title">
<svg-icon :iconClass="routeItem.meta.icon" className="console-svg"></svg-icon>
<span slot="title" class="">{{ routeItem.meta.name}}</span>
</template>
<!-- 子级菜单 -->
<el-menu-item v-for="(subItem, index) in routeItem.children" :key="subItem.id" :index="subItem.path">{{subItem.meta.name}}</el-menu-item>
</el-submenu>
</template>
使用flex布局
router.beforeEach路由守卫
router/premit.js
参数:
next
to 要进入的页面
from 离开之前的页面(上一个)
函数:
next():一定要调用这个方法来resolve这个钩子,执行效果依赖next方法的调用参数
守卫或登录流程
检查token是否存在,从cookie中获取token,如果不存在,进行next跳转到登录页面。并且在跳转之前,要判断是否存在下一个页面(白名单判断),防止守卫进入死循环。:
1. 直接进入index的时候,参数to被改变成“/index”,触发路由指向,就会在进行beforeEach
2. 再一次next指向login,再次发生路由指向,再跑beforeEach,参数的头被改变成“/login”
3. 白名单判断存在,直接执行next(),因为没有参数,所以不会再次beforeEach
使用fill改变svg颜色
fill:currentColor
color:red
currentColor也可以全局定义
父子组件传值
propdatas
watch
computed
默认get方法返回,监听到值得的变化就可以进行属性的计算并返回值或字符串
set方法 :值先通过get计算,再传给set
使用vuex
建立store.js
四个属性
getters
时候我们需要从 store 中的 state 中派生出一些状态,
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,
且只有当它的依赖值发生了改变才会被重新计算。
const getters = {
teamId: state => state.teamId,
userRole: state => state.userRole
}
state
Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。
至此它便作为一个“唯一数据源 (SSOT (opens new window))”而存在。
这也意味着,每个应用将仅仅包含一个 store 实例。
单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
const state = {
// token
token: cookie.get('userToken') || '',
userId: cookie.get('userId') || '',
workId: cookie.get('workId') || ''
}
mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:
每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
你不能直接调用一个 mutation handler。这个选项更像是事件注册:
“当触发一个类型为 SET_TOKEN的 mutation 时,调用此函数。”
要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:
const mutations = {
SET_TOKEN (state, value) {
state.token = value
}
}
store.commit(SET_TOKEN)
actions
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
注册一个简单的 action:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,
因此你可以调用 context.commit 提交一个 mutation,
或者通过 context.state 和 context.getters 来获取 state 和 getters。
actions: {
increment ({ commit }) {
commit('increment')
}
}
#分发 Action
Action 通过 store.dispatch 方法触发:
store.dispatch('increment')
通过vuex修改菜单的状态值,确定展开或收缩
在header获取状态值,点击并且修改(root.$store.comit())
,在Nav中使用computed监听状态值变化
并且在布局的index.vue中监听状态值,
当变化时,通过一个class(open或close)使index整体移动,并且过渡
modules模块管理状态数据
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。
当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。
每个模块拥有自己的 state、mutation、action、getter、
甚至是嵌套子模块——从上至下进行同样方式的分割:
目录结构:
把各个属性提取出来定义,解决命名空间问题
命名空间
默认情况下,模块内部的 action、mutation 和 getter
是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
如果希望你的模块具有更高的封装度和复用性,
你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。
当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。例子:
const store = new Vuex.Store({
modules: {
account: {
namespaced: true,
// 模块内容(module assets)
state: () => ({ ... }), // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
getters: {
isAdmin () { ... } // -> getters['account/isAdmin']
},
actions: {
login () { ... } // -> dispatch('account/login')
},
mutations: {
login () { ... } // -> commit('account/login')
},
// 嵌套模块
modules: {
// 继承父模块的命名空间
myPage: {
state: () => ({ ... }),
getters: {
profile () { ... } // -> getters['account/profile']
}
},
// 进一步嵌套命名空间
posts: {
namespaced: true,
state: () => ({ ... }),
getters: {
popular () { ... } // -> getters['account/posts/popular']
}
}
}
}
}
})
全局方法export install
注册global.js,存放全局方法
vue2.0:
vue3.0:
可以通过重命名来区分命名空间
vue3.0封装接口
接口统一封装在api文件夹中,例子:
目录结构:
api文件:
在vuex中的moudle调用:
自适应布局学习
rem:
1. rem单位
rem是一个灵活的、可扩展的单位,由浏览器转化像素并显示。与em单位不同,rem单位无论嵌套层级如何,都只相对于浏览器的根元素(HTML元素)的font-size。默认情况下,html元素的font-size为12px,所以:
1 rem = 12px
为了计算方便,通常可以将html的font-size设置成:
html{ font-size: 67.5% }
这种情况下:
1 rem = 10px
2.通过rem来实现响应式布局
rem单位都是相对于根元素html的font-size来决定大小的,根元素的font-size相当于提供了一个基准,当页面的size发生变化时,只需要改变font-size的值,那么以rem为固定单位的元素的大小也会发生响应的变化。
需要根据视图容器的大小,动态的改变font-size即可。
function refreshRem() {
var docEl = doc.documentElement;
var width = docEl.getBoundingClientRect().width;
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', refreshRem);
上将视图容器分为10份,font-size用十分之一的宽度来表示,最后在header标签中执行这段代码,就可以动态定义font-size的大小,从而1rem在不同的视觉容器中表示不同的大小,用rem固定单位可以实现不同容器内布局的自适应。
3. rem2px和px2rem
如果在响应式布局中使用rem单位,那么存在一个单位换算的问题,rem2px表示从rem换算成px,这个就不说了,只要rem乘以相应的font-size中的大小,就能换算成px。更多的应用是px2rem,表示的是从px转化为rem。
比如给定的视觉稿为750px(物理像素),如果我们要将所有的布局单位都用rem来表示
一种比较方便的解决方法就是,在css中我们还是用px来表示元素的大小,最后编写完css代码之后,将css文件中的所有px单位,转化成rem单位。
px2rem的原理也很简单,重点在于预处理以px为单位的css文件,处理后将所有的px变成rem单位。可以通过两种方式来实现:
// webpack loader的形式:
npm install px2rem-loader
//在webpack的配置文件中:
module.exports = {
// ...
module: {
rules: [{
test: /\.css$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'px2rem-loader',
// options here
options: {
remUni: 75,
remPrecision: 8
}
}]
}]
}
}
//webpack中使用postcss plugin
npm install postcss-loader
//在webpack的plugin中:
var px2rem = require('postcss-px2rem');
module.exports = {
module: {
loaders: [
{
test: /\.css$/,
loader: "style-loader!css-loader!postcss-loader"
}
]
},
postcss: function() {
return [px2rem({remUnit: 75})];
}
}
4.vue 中的 rem 布局
由于该项目使用vue3,所以总结vue3 中的用法
//安装lib-flexible
npm install lib-flexible -S
//引入lib-flexible
//在main.js中引入lib-flexible-->
import 'lib-flexible/flexible'S
pxtorem:将项目中css的px转成rem单位,免去计算烦恼
1)安装postcss-pxtorem
S
npm install postcss-pxtorem -S
// 配置postcss-pxtorem
<!--package.json内,在postcss内添加-->
"postcss": {
"plugins": {
"autoprefixer": {},
"postcss-pxtorem": {
"rootValue": 75 // 设计稿宽度的1/10,
"propList":['*'],
// 需要做转化处理的属性,如`hight`、`width`、`margin`等,`*`表示全部
}
}
}
注意:
1、pxtorem中,对于想忽略的px写成大写即可
5. rem 布局的缺点
通过rem单位,可以实现响应式的布局,特别是引入相应的postcss相关插件,免去了设计稿中的px到rem的计算。
rem单位在国外的一些网站也有使用,这里所说的rem来实现布局的缺点,或者说是小缺陷是:
在响应式布局中,必须通过js来动态控制根元素font-size的大小。
也就是说css样式和js代码有一定的耦合性。且必须将改变font-size的代码放在css样式之前