VUE学习随笔

 

 

vue.js是一套构建用户界面的渐进式框架。vue采用自底向上增量开发的设计。vue的核心库只关心视图层,非常容易学习,非常容易与其它库和已有项目整合。vue完全有能力驱动采用单文件组件和vue生态系统支持的库开发的复杂单页应用。

vue.js的目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。

 

总体框架

一个vue-cli的项目结构如下,其中src文件夹是需要掌握的,所以本文也重点讲解其中的文件,至于其他相关文件,了解一下即可。

文件结构细分

 

1.build——[webpack配置]

build文件主要是webpack的配置,主要启动文件是dev-server.js,当我们输入npm run dev首先启动的就是dev-server.js,它会去检查node及npm版本,加载配置文件,启动服务。

 

2.config——[vue项目配置]

config文件主要是项目相关配置,我们常用的就是当端口冲突时配置监听端口,打包输出路径及命名等

 

3.node_modules——[依赖包]

node_modules里面是项目依赖包,其中包括很多基础依赖,自己也可以根据需要安装其他依赖。安装方法为打开cmd,进入项目目录,输入npm install [依赖包名称],回车。

在两种情况下我们会自己去安装依赖:

(1)项目运行缺少该依赖包:例如项目加载外部css会用到的css-loader,路由跳转vue-loader等(安装方法示例:npm install css-loader)

(2)安装插件:如vux(基于WEUI的移动端组件库),vue-swiper(轮播插件

注:有时会安装指定依赖版本,需在依赖包名称后加上版本号信息,如安装11.1.4版本的vue-loader,输入npm install [email protected]

 

4.src——[项目核心文件] 

项目核心文件前面已经进行了简单的说明,接下来重点讲解main.js,App.vue,及router的index.js

 

4.1 index.html——[主页]

index.html如其他html一样,但一般只定义一个空的根节点,在main.js里面定义的实例将挂载在根节点下,内容都通过vue组件来填充

 

4.2 App.vue——[根组件]

一个vue页面通常由三部分组成:模板(template)、js(script)、样式(style)

【template】

其中模板只能包含一个父节点,也就是说顶层的div只能有一个(例如上图,父节点为#app的div,其没有兄弟节点)

是子路由视图,后面的路由页面都显示在此处

打一个比喻吧,类似于一个插槽,跳转某个路由时,该路由下的页面就插在这个插槽中渲染显示

 

【script】

vue通常用es6来写,用export default导出,其下面可以包含数据data,生命周期(mounted等),方法(methods)等,具体语法请看vue.js文档,在后面我也会通过例子来说明。

 

【style】

样式通过style标签包裹,默认是影响全局的,如需定义作用域只在该组件下起作用,需在标签上加scoped,

如要引入外部css文件,首先需给项目安装css-loader依赖包,打开cmd,进入项目目录,输入npm install css-loader,回车。安装完成后,就可以在style标签下import所需的css文件,例如:

      

这样,我们就可以把style下的样式封装起来,写到css文件夹,再引入到页面使用,整个vue页面也看上去更简洁。

 

4.3 main.js——[入口文件]

main.js主要是引入vue框架,根组件及路由设置,并且定义vue实例,下图中的

components:{App}就是引入的根组件App.vue

后期还可以引入插件,当然首先得安装插件。

 

4.4 router——[路由配置]

router文件夹下,有一个index.js,即为路由配置文件

这里定义了路径为'/'的路由,该路由对应的页面是Hello组件,所以当我们在浏览器url访问http://localhost:8080/#/时就渲染的Hello组件

类似的,我们可以设置多个路由,‘/index’,'/list'之类的,当然首先得引入该组件,再为该组件设置路由。

 

项目加载分析

1、项目启动分析

①入口文件main.js——②入口文件中配置了相关的模板注入信息——③扫描路由。先找到公共路由,再根据注入的模板信息扫描模块中的路由。

VUE学习随笔_第1张图片

2、发送请求获取数据执行分析

①发送请求——②根据请求路由到相关页面——③页面创建后调用钩子函数调用需要用的js方法——④js方法访问API方法——⑤根据API访问后台接口——⑥后台接口返回相关数据——⑦修改数据模型——⑧数据模型双向绑定。

 VUE学习随笔_第2张图片

3、路由页面分析

①公共路由与模块路由启动后被扫描。

②根据访问路径查找相关路径对应信息:

a、先找到父路径:path: '/saas-clients',//父路径

b、找到子路径:path: 'index'

c、根据子路径跳转视图地址:component: _import('saas-clients/pages/index'), //跳转的vue视图

d、找到module-saas-clients模块目录下的pages目录下的index.vue文件

e、跳转地址的主目录为saas-clients,而并非module-saas-clients是如何对应的?

根据公共路由中import_development.js、import_production.js2个文件的配置,根据vue项目规则自动加的前缀。

VUE学习随笔_第3张图片

 

elementui自定义主题(任意颜色)换肤功能

我的项目中使用了scss,elementui官网提供了解决方案如下:

在项目中改变 SCSS 变量
 
Element 的 theme-chalk 使用 SCSS 编写,如果你的项目也使用了 SCSS,那么可以直接在项目中改变 Element 的样式变量。
1. 新建一个样式文件,例如 element-variables.scss,写入以下内容:
 
/* 改变主题色变量 */
$--color-primary: teal;
 
/* 改变 icon 字体路径变量,必需 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
 
@import "~element-ui/packages/theme-chalk/src/index";
 
2. 之后,在项目的入口文件中,直接引入以上样式文件即可(无需引入 Element 编译好的 CSS 文件):
 
import Vue from 'vue'
import Element from 'element-ui'
import './element-variables.scss'
 
Vue.use(Element)
需要注意的是,覆盖字体路径变量是必需的,将其赋值为 Element 中 icon 图标所在的相对路径即可。

以上方法,我们修改主题色变量 $--color-primary 的值,然后在项目入口文件 main.js 中引入该样式文件,覆盖elementui的css文件,即可实现换肤。 

那么怎么做到自定义任意颜色的主题呢?大致思路如下:

  • 1.使用 el-color-picker 组件,供用户选择颜色
  • 2.监听颜色的变化,创建 style 标签,生成样式内容
  • 3.将创建好的样式内容插入 head 中

实际步骤如下:

  • 1.在项目中新建一个scss文件,比如就叫 elementui-variables.scss 

内容如下:

/* theme color */
$--color-primary: #1890ff;
$--color-success: #13ce66;
$--color-warning: #FFBA00;
$--color-danger: #ff4949;
// $--color-info: #1E1E1E;
 
$--button-font-weight: 400;
 
// $--color-text-regular: #1f2d3d;
 
$--border-color-light: #dfe4ed;
$--border-color-lighter: #e6ebf5;
 
$--table-border:1px solid #dfe6ec;
 
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
 
// @import "~element-ui/packages/theme-chalk/src/index";
 
:export {
  theme: $--color-primary;
}

2.考虑到项目全局都有可能使用到颜色这个变量,所以决定用vuex,如图:新建文件 settings.js

settings.js 内容如下,theme 的初始值为 elementui-variables.scss 中定义的theme。

import variables from '@/styles/element-variables.scss'
 
const settings = {
  state: {
    theme: variables.theme,
  },
  mutations: {
    CHANGE_SETTING: (state, { key, value }) => {
      if (state.hasOwnProperty(key)) {
        state[key] = value
      }
    }
  },
  actions: {
    changeSetting({ commit }, data) {
      commit('CHANGE_SETTING', data)
    }
  }
 
}
 
export default settings
  • 3.新建一个组件(一般在components目录下,我将它命名为ThemePicker),用于监听颜色变量 theme 的改变,然后 getHandler 函数生成样式文件,插入head中。在这里我遇到了一个问题,如果使用 document.head.appendChild(styleTag) ,页面就会变成一片空白,然后我就在想有可能是样式的顺序导致一些有用的样式被覆盖了,所以我就讲它改为 document.getElementsByTagName('style')[0].insertBefore(styleTag, null) ; 完美解决问题。

ThemePicker文件内容如下,可以看到默认的颜色是 this.$store.state.settings.theme ,它是在 elementui-variables.scss 中定义的。


 


辅助文件:utils/color.js

import color from 'css-color-function'
import formula from './formula.json'

const generateColors = primary => {
  let colors = {}
  console.log("当前颜色:" , primary)
  Object.keys(formula).forEach(key => {
    const value = formula[key].replace(/primary/g, primary)
    colors[key] = color.convert(value)
  })
  return colors
}

export default generateColors

页面上有些组件的样式可能是自定义的,不会随 theme 一起变化,可这么实现:

     
        {{ tag.name }}
        
     
computed: {
    //...,
    theme() {
      return this.$store.state.settings.theme
    }
  },

4.最后在页面上使用 ThemePicker 组件即可:

实际效果录屏:

 

 

Vue项目引入阿里图标

引入步骤

1、访问网址https://www.iconfont.cn/

2、选择好后加入购物车

VUE学习随笔_第4张图片

如何批量添加阿里巴巴iconfont图标到购物车

在页面上右键--审查元素,切换到console 控制台 输入如下代码,其实就是触发点击事件,可以一次性选择当前页面所有的图标

var span = document.querySelectorAll('.icon-cover');
for (var i = 0, len = span.length; i < len; i++) {
     console.log(span[i].querySelector('span').click());
}

VUE学习随笔_第5张图片

3、进入购物车,添加至项目

VUE学习随笔_第6张图片

4、进入我的项目,下载到本地

VUE学习随笔_第7张图片

VUE学习随笔_第8张图片

5、将解压后的文件放入目标文件夹下

VUE学习随笔_第9张图片

6、在main.js文件内全局引入 阿里云字体图标 css,记得使用 路径要正确,如果此时编译不正确,说明 引用路径存在问题

为避免出现图标方框的情况,请对font进行初始化

在reset.css 或者全局index.css中加入如下代码

// 阿里字体图标设置
.icon, .iconfont {
  font-family:"iconfont" !important;
  font-size:16px;
  font-style:normal;
  -webkit-font-smoothing: antialiased;
  -webkit-text-stroke-width: 0.2px;
  -moz-osx-font-smoothing: grayscale;
}

7、项目中使用字体图标,就可以使用了

(3)Symbol  SVG图片格式

 

①支持多色图标了,不再受单色限制。

②支持像字体那样通过font-size,color来调整样式。

③支持 ie9+

④可利用CSS实现动画。

⑤减少HTTP请求。

⑥矢量,缩放不失真

⑦可以很精细的控制SVG图标的每一部分

使用方法:
第一步:拷贝下载项目,复制inconfont.js到资源文件目录下,并引入inonfont.js文件

引入 ./iconfont.js

第二步:加入通用css代码(引入一次就行):

第三步:挑选相应图标并获取类名,应用于页面:

 

vue项目中引入阿里图标SVG

引入过程中出现的问题:页面没有出现图标,原因:在main.js中没有引入iconfont.js

1、阿里demo中的引入方式:

 

VUE学习随笔_第10张图片

2、我的引入方式(参考别人的项目)

   上图中的引入方式,在iconfonts.js中注册了标签

  我的方式是在上面的基础上封装了一层,每次使用的时候可以不用写

   我的目录结构:

VUE学习随笔_第11张图片

icons/svg中放所有的图标文件

1)index.js中代码功能,注册全局标签,并获取所有的svg文件,index.js中的代码如下:

import Vue from 'vue'
import SvgIcon from '../../components/SvgIcon'// svg component

// register globally
Vue.component('svg-icon', SvgIcon)

const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

2)SvgIcon组件中的代码,主要共功能将引入图标的代码封装到组件中,并注册为全局标签使用

<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :href="iconName" />

svg>
template>

<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '../utils/validate'

export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
script>

<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}

.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
style>

3)在main.js中引入即可

import './assets/icons'
import './assets/fonts/iconfont.js'

 

store的值刷新就被覆盖解决方案

最近在用vue写pc端项目,用vuex来做全局的状态管理, 发现当刷新网页后,保存在vuex实例store里的数据会丢失。

1. 产生原因
2. 解决思路
3. 解决过程
1. 产生原因
其实很简单,因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值。

2. 解决思路
一种是state里的数据全部是通过请求来触发action或mutation来改变

一种是将state里的数据保存一份到本地存储(localStorage、sessionStorage、cookie)中

很显然,第一种方案基本不可行,除非项目很小或者vuex存储的数据很少。而第二种可以保证刷新页面数据不丢失且易于读取。

3. 解决过程
首先得选择合适的客户端存储

localStorage是永久存储在本地,除非你主动去删除;

sessionStorage是存储到当前页面关闭为止;

cookie则根据你设置的有效时间来存储,但缺点是不能储存大数据且不易读取。

我选择的是sessionStorage,选择的原因vue是单页面应用,操作都是在一个页面跳转路由,另一个原因是sessionStorage可以保证打开页面时sessionStorage的数据为空,而如果是localStorage则会读取上一次打开页面的数据。

然后是怎么用sessionStorage来保存state里的数据。

第一种方案

由于state里的数据是响应式,所以sessionStorage存储也要跟随变化。又由于vuex规定所有state里数据必须通过mutation方法来修改,所以第一种方案就是mutation修改state的同时修改sessionStorage对应存储的属性

第二种方案

第一种方案确实可以解决问题,但这种方法很明显让人觉得怪异,都这样了,那不如直接用sessionStorage来做状态管理。

那怎么才能不用每次修改state时同时也要修改sessionStorage呢?这时我们可以换一个思路,因为我们是只有在刷新页面时才会丢失state里的数据,那有没有办法在点击页面刷新时先将state数据保存到sessionStorage,然后才真正刷新页面?

当然有,beforeunload这个事件在页面刷新时先触发的。那这个事件应该在哪里触发呢?我们总不能每个页面都监听这个事件,所以我选择放在app.vue这个入口组件中,这样就可以保证每次刷新页面都可以触发。

具体的代码如下:在入口App.vue下加入






问题汇总

1、VUE问题

1.1、jsp中使用vue,加载页面显示{}的问题

描述:在jsp中vue的时候,页面加载的时候总会有{{ }}闪烁,看着太烦人了。

解决方案:

①样式中添加

[v-cloak] {
    display: none;
}

 ②vue根元素添加


    ... 其它元素 ...
    

1.2、动态加载代码 点击事件不管用 解决办法

vue 中拼接代码

VUE学习随笔_第12张图片

vue 中处理

1.3、vue使用el-dialog关闭后重置数据的最佳方法

此方法试用所有需要重置数据的场景

el-dialog打开一次之后,再次打开之前的数据不会销毁,依然存在。

我们需要在关闭后重新初始化数据。

重置表单的方法

this.$refs[formRef].resetFields();
复制代码

有些数据不是表单中的数据,也需要重置。

难道一个个的重新手动赋值吗?当然可以,就是比较麻烦。好在vue帮我们保存了一份原始数据,直接把data复制为原始数据即可

this.$data = this.$options.data();

以上就可以正常运行, 但是如果data中有表单验证相关,会导致控制台出现报错信息,如下面代码中的ruleValidate,排除即可。

data () {
  return {
    dialogVisible: false,
    submitLoading: false,
    model: {
      id: 0,
      carCard: "",
      driver: "",
      remark: "",
    },
    ruleValidate: {
      carCard: {required: true, message: "不能为空", trigger: "blur"},
    },
  };
},

重置表单数据,使用的地方特别多,我们封装为全局方法

//重置表单,formRef为表单的ref值,excludeFields为要排除重新初始化值得属性
Vue.prototype.$reset = function (formRef, ...excludeFields) {
  this.$refs[formRef].resetFields();
  let obj1 = this.$data;
  let obj2 = this.$options.data.call(this);
  if (!excludeFields || excludeFields.length === 0) {
    excludeFields = ["ruleValidate"];
  }
  for (let attrName in obj1) {
    if (excludeFields && excludeFields.includes(attrName)) {
      continue;
    }
    obj1[attrName] = obj2[attrName];
  }
};

使用方法

2、GIT提交冲突解决

VUE学习随笔_第13张图片

3、element使用问题

3.1、el-dialog相互调用是遮罩问题

A页面中调起B(dialog)页面,B(dialog)页面调起C(dialog)页面,会出现遮罩问题,如下图:

VUE学习随笔_第14张图片

解决办法:在C页面中加入append-to-body,如下图:

VUE学习随笔_第15张图片

你可能感兴趣的:(JAVA,WEB)