目录
1.iconfont
2. sass版本问题
3.屏幕高宽度自适应
4. 跨域
5. 拦截器
6.项目插件安装
7.登录鉴权(单路由)
8.插件引入、持久化、字体图标、富文本、时间戳
9. 跳转、返回、前进和后退
10.echarts图表的使用
11. vue组件中引入js文件(放script中)
12.vue组件中引入css文件(放style中)
13.插槽
14.vue六种传值方式(属性传值、$refs、$parent、通知传值(广播传值)、本地传值、路由传值)
15.增删改查
16.登录+验证规则+重置
17.模拟数据
18.电话邮箱正则验证
19.dialog弹框(可用于增删改查)
20.登录的盒子居中
21.api封装
Vue脚手架中盒子高度设置问题:height:100vh; //es6语法
-
-
-
1、vue中sass安装使用============================================================
方法一:
我本地是将 "sass-loader": "^8.0.0",更换成了 "sass-loader": "^7.3.1",
卸载当前版本 npm uninstall sass-loader
安装 npm install sass-loader@7.3.1 --save-dev
方法二:
如若不行,此时运行按照提示执行 npm rebuild node-sass 命令
(如若还不行,则先运行npm install node-sass命令执行)
mounted() {
// 调用自动调节
this.fc_height();
},
methods: {
// 获取屏幕宽高自动调节
fc_height() {
let html = document.documentElement || document.body;
let height = html.clientHeight - 60;
let aside = document.querySelector('.el-aside');
aside.style.height = height + 'px';
}
}
proxyTable: {
'/admin': { //代理api
target: 'http://ceshi5.dishait.cn/admin', //服务器api地址
ws: true, // proxy websockets
changeOrigin: true, //是否跨域
pathRewrite: { //重写路径
'^/admin': ''
}
}
},
//添加请求拦截器
axios.interceptors.request.use(config => {
console.log(config)
// 从sessionStorage获取token值,然后设置给请求头
config.headers.Authorization = window.sessionStorage.getItem('token')
// 在最后必须 return config
return config
})
npm i element-ui -S
npm install axios --save
npm install echarts --save
npm install vant --save
npm install vuex -s
cnpm install node-sass@4.14.1 sass-loader@7.3.1 -s
beforeEnter(to,from,next){
if(sessionStorage.getItem("token")){
next()
}else {
alert("请先登录");
next('/')
}
},
// 引入vuex
import Vuex from 'vuex';
// 持久化=====================================================================
import VuexPersistence from 'vuex-persist' //store中引入
const vuexLocal = new VuexPersistence({ //store中引入
storage: window.localStorage
})
plugins: [vuexLocal.plugin] //store中引入
cnpm install --save vuex-persist //下载
// 引入vant组件====================================================================
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
// 引入第三方控件[分类参数]===============================================
npm i vue-table-with-tree-grid -S //下载
import TreeTable from 'vue-table-with-tree-grid' //在main.js中使用
Vue.config.productionTip = false //在main.js中使用
//全局注册组件===============================================
Vue.component("tree-table", TreeTable)
// 导入字体图标===============================================
import './assets/fonts/iconfont.css'
// 导入富文本编辑器(用法)===============================================
import VueQuillEditor from 'vue-quill-editor'
// require styles 导入富文本编辑器对应的样式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
// 将富文本编辑器,注册为全局可用的组件===============================================
Vue.use(VueQuillEditor)
// 时间戳转换===============================================
Vue.filter('dateFormat', function(originVal) {
const dt = new Date(originVal)
const y = dt.getFullYear()
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
const d = (dt.getDate() + '').padStart(2, '0')
const hh = (dt.getHours() + '').padStart(2, '0')
const mm = (dt.getMinutes() + '').padStart(2, '0')
const ss = (dt.getSeconds() + '').padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
})
// 引入ElementUI组件===============================================
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
//Echarts图表引入===============================================
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
//引入axios和配置请求根路径===============================================
import axios from 'axios'
axios.defaults.baseURL = 'https://www.liulongbin.top:8888/api/private/v1'
// 添加请求拦截器===============================================
axios.interceptors.request.use(config => {
console.log(config)
// 从sessionStorage获取token值,然后设置给请求头
config.headers.Authorization = window.sessionStorage.getItem('token')
// 在最后必须 return config
return config
})
Vue.prototype.$http = axios
编程导航
我们可以用在渲染完元素不方便添加router-link的使用
编程导航提供的方法:
this.$router.push(路径) 跳转到哪个路由
this.$router.go(-1) 返回上一级
vue还提供一种方式 来实现导航 编程式导航 在事件中通过this.$router的方法来实现
我们主要掌握的方法
push() 进入到哪个页面
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
go(-num) 返回哪个页面
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
replace()
跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。 没有办法使用go()返回了
this.$route 和this.$router的区别:
this.$route 路由信息对象 可以获取参数列表
this.$router路由实例对象 可以实现页面的转换
import { login } from "../scripts/apis.js";
import login from "../scripts/apis.scss";
import login from "../scripts/apis.css";
匿名插槽:子组件 父组件今天天气阳光明媚
具名插槽:子组件 父组件 今天天气挺好
作用域插槽:
子组件
父组件
{{scope.nickName}}
14.vue六种传值方式(属性传值、$refs、$parent、通知传值(广播传值)、本地传值、路由传值)
在介绍组件传值之前先明确三种组件关系:父子组件、兄弟组件、表兄弟组件(a1,a2,a3 | a1和a3)、无关系组件(a,b)
1.属性传值:父传子
可传值类型:固定值 绑定属性 方法 本类对象
父:
子:
props:{
'mess':String,
'bindMsg':[String, Number],
'run':Function,
'fatherThis':Object,
}
可传值类型:属性 方法
2.$refs:子传父与vue获取元素ref="dataNum"(this.$refs.dataNum.dataset.num)
父: 使用:this.$refs.header.msg
this.$refs.header.属性
this.$refs.header.方法
子:data(){ return{ msg:"我是子组件header的值哟" } }
vue获取元素:
55
this.$refs.dataNum.dataset.num
3.$parent:父传子
可传值类型:属性 方法
直接在子组件中使用this.$parent.XX,不需要做任何多余操作
子 :getFatherProp(){
alert(this.$parent.fatherMsg);
},
4.兄弟传兄弟————通知传值(广播传值)
只传基本数据类型,不能传方法。
传输:通过 bus.$emit('名称','数据')传播数据
接收:bus.$on('名称',function(){})
示例:example
定义bus.js文件:import Vue from 'vue' var bus= new Vue(); export default bus;
然后引入:import vueEvents from '../Model/vueEvent.js'
5.本地传值( localStorage和vuex都是本地存储)
本地传值方式对于Vue而言有两种,一种是JS的localStorage,另一种Vuex。
1. localStorage
存:
localStorage.setItem('tolist',JSON.stringify(this.tolist));
取:
var tolist = JSON.parse(localStorage.getItem('tolist'));
2. Vuex
使用数据: this.\$store.state.count
调用方法: this.$store.commit('incCount');
1.定义存储数据 var state = { count:1,}
2. //类似于计算属性 state里边的数据改变时候触发的方法。 可以做一些操作 并且可以有返回值
var getterfl={
completedCountChange(state){
return state.count * 2 +'位';
}
}
3.Action 类似于 mutation,不同在于: Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作
var actionfl = {
asynIncCount(context){
//因此你可以调用context.commit来提交一个mutation 使用action需要用dispatch
context.commit('incCount');
}
}
6.路由传值(this.$router.push)
1.父组件push使用this.$router.push
2.在子组件中获取参数的时候是this.$route.params
1.动态路由传值
1.1 配置动态路由
routes:[
//动态路由参数 以冒号开头
{path:'/user/:id',conponent:User}
]
1.2 传值
第一种写法 : 传值
第二种写法 : goToUser(id) {
this.$router.push( {path:'/user/'+id});
}
1.3 在对应页面取值
this.$route.params; //结果:{id:123}
2. Get传值(类似HTMLGet传值)
6.路由传值(this.$router.push)
1.父组件push使用this.$router.push
2.在子组件中获取参数的时候是this.$route.params
1.动态路由传值
1.1 配置动态路由
routes:[
//动态路由参数 以冒号开头
{path:'/user/:id',conponent:User}
]
1.2 传值
第一种写法 : 传值
第二种写法 : goToUser(id) {
this.$router.push( {path:'/user/'+id});
}
1.3 在对应页面取值
this.$route.params; //结果:{id:123}
2. Get传值(类似HTMLGet传值)
2.1 配置路由
const routes = [{path:'/user',component:User},]
2.2 传值
第一种写法 : 传值
第二种写法 : goToUser(id) {
//'user' 是路径名称
this.$router.push({path:'user',query:{ID:id}});
}
2.3 在对应页面取值
this.$route.query; //结果 {id:123}
3. 命名路由push传值
3.1 配置路由
const routes = [{path:'/user',name: 'User',component:User},]
3.2 传值
goToUser(id) {
//'User' 是路径重命名
this.$router.push({name:'User',params:{ID:id}});
}
3.3 在对应页面取值
this.$route.params; //结果:{id:123}
15.增删改查
增:
删:
改:
查询/搜索功能:
eg:"ruleForm.auditState"
//把参数写在需要的请求列表里:
const params = {
areaName: this.ruleForm.areaName ? this.ruleForm.areaName : null,
cityName: this.ruleForm.cityName ? this.ruleForm.cityName : null,
// cityCode: this.cityCode ? this.cityCode : null,
auditState: this.ruleForm.auditState ? this.ruleForm.auditState : null,
pageNum: this.pageNum,
pageSize: this.pageSize
}
========================================================================================
消息提示:两种书写方式
1.this.$message({
type: 'success',
message: '禁用成功!'
})
2.this.$message.success('登录成功');
16.登录+验证规则+重置
Login
Reset
17.模拟数据
下拉框:
statusArr: [{ id: 1, name: '待审核' }, { id: 2, name: '通过' }, { id: 3, name: '拒绝' }],
18.电话邮箱正则验证
data() {
var checkEmail = (rule, value, cb) => {
const regEmail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;
if (regEmail.test(value)) {
return cb();
}
cb(new Error('请输入正确的邮箱'));
};
// 验证手机号
var checkMobile = (rule, value, cb) => {
const regMobile = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
if (regMobile.test(value)) {
return cb();
}
cb(new Error('请输入合法的手机号'));
};
return {
// 验证规则
addFormRules: {
email: [{
required: true,
message: '请输入邮箱',
trigger: 'blur'
}, {
validator: checkEmail,
trigger: 'blur'
}],
}
}
19.dialog弹框(可用于增删改查)
20.登录的盒子居中
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
21.api封装
import axios from 'axios' // 引入axios
import { ElMessage, ElMessageBox } from 'element-plus'
import { store } from '@/store'
import { emitter } from '@/utils/bus.js'
const service = axios.create({
baseURL: import.meta.env.VITE_BASE_API,
timeout: 99999
})
let acitveAxios = 0
let timer
const showLoading = () => {
acitveAxios++
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
if (acitveAxios > 0) {
emitter.emit('showLoading')
}
}, 400)
}
const closeLoading = () => {
acitveAxios--
if (acitveAxios <= 0) {
clearTimeout(timer)
emitter.emit('closeLoading')
}
}
// http request 拦截器
service.interceptors.request.use(
config => {
if (!config.donNotShowLoading) {
showLoading()
}
const token = store.getters['user/token']
const user = store.getters['user/userInfo']
config.data = JSON.stringify(config.data)
config.headers = {
'Content-Type': 'application/json',
'x-token': token,
'x-user-id': user.ID
}
return config
},
error => {
closeLoading()
ElMessage({
showClose: true,
message: error,
type: 'error'
})
return error
}
)
// http response 拦截器
service.interceptors.response.use(
response => {
closeLoading()
if (response.headers['new-token']) {
store.commit('user/setToken', response.headers['new-token'])
}
if (response.data.code === 0 || response.headers.success === 'true') {
if (response.headers.msg) {
response.data.msg = decodeURI(response.headers.msg)
}
return response.data
} else {
ElMessage({
showClose: true,
message: response.data.msg,
type: 'error'
})
if (response.data.data && response.data.data.reload) {
store.commit('user/LoginOut')
}
return response.data.msg ? response.data : response
}
},
error => {
closeLoading()
switch (error.response.status) {
case 500:
ElMessageBox.confirm(`
检测到接口错误${error}
错误码 500 :此类错误内容常见于后台panic,请先查看后台日志,如果影响您正常使用可强制登出清理缓存
`, '接口报错', {
dangerouslyUseHTMLString: true,
distinguishCancelAndClose: true,
confirmButtonText: '清理缓存',
cancelButtonText: '取消'
})
.then(() => {
store.commit('user/LoginOut')
})
break
case 404:
ElMessageBox.confirm(`
检测到接口错误${error}
错误码 404 :此类错误多为接口未注册(或未重启)或者请求路径(方法)与api路径(方法)不符--如果为自动化代码请检查是否存在空格
`, '接口报错', {
dangerouslyUseHTMLString: true,
distinguishCancelAndClose: true,
confirmButtonText: '我知道了',
cancelButtonText: '取消'
})
break
}
return error
}
)
export default service
import service from '@/utils/request'
export const getApiList = (data) => {
return service({
url: '/api/getApiList',
method: 'post',
data
})
}
//在使用请求的组件里面引入
import { mapActions } from 'vuex'
import { captcha } from '@/api/user'
import { checkDB } from '@/api/initdb'
export default {
name: 'Login',
data() {
return(){
}
}
}
21.Vue.js Ajax(axios)
GET 方法传递参数格式如下:
传递参数说明
// 直接在 URL 上添加参数 ID=12345
axios.get("/user?ID=12345")
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 也可以通过 params 设置参数:
axios.get("/user", {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
POST 方法传递参数格式如下:
传递参数说明
axios.post("/user", {
firstName: "Fred", // 参数 firstName
lastName: "Flintstone" // 参数 lastName
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
执行多个并发请求
实例
function getUserAccount() {
return axios.get("/user/12345");
}
function getUserPermissions() {
return axios.get("/user/12345/permissions");
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// 两个请求现在都执行完成
}));
22.JSON.parse()
在接收服务器数据时一般是字符串。
我们可以使用 JSON.parse() 方法将数据转换为 JavaScript 对象。
JSON.parse(text[, reviver])
参数说明:
- text:必需, 一个有效的 JSON 字符串。
- reviver: 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。
23.vuex
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
- Vuex 是一个数据管理工具,我们可以通过它简化组件间的数据共享问题。
- Vuex 的安装和使用方法。
- 使用 new Vuex.Store ({…}) 创建数据仓库。
24.vue3升级安装和卸载安装
1. 安装vue-cli
1.1 卸载旧版本
npm uninstall vue-cli -g
yarn global remove vue-cli
1.2 安装新的包
npm install -g @vue/cli
yarn global add @vue/cli
1.3 升级全局的 Vue CLI 包
npm update -g @vue/cli
yarn global upgrade --latest @vue/cli
1.4 查看当前 Vue CLI 版本
vue --version
vue -V
25.vue3项目初始化
创建my-project项目:vue create my-project
提供了三种设置:Vue2版、Vue3版、手动选择功能;
按键盘上下键选择默认(default)还是手动(Manually);
这里我选择第三种:Manually select features;
回车键确认;
3. 选择配置
选择自己所要集成的配置(格键是选中与取消,A键是全选,回车确定)
这里我的选择如下:
配置项:
(*) Choose Vue version:选择 Vue 版本
(*)Babel:支持使用Babel编译器
(*)TypeScript:支持使用 TypeScript 书写源码
( )Progressive Web App (PWA) Support:支持PWA
(*) Router:支持 vue-router
(*)Vuex:支持 vuex
(*)CSS Pre-processors:支持 CSS 预处理器
(*)Linter / Formatter:支持代码风格检查和格式化
( )Unit Testing:支持单元测试
( )E2E Testing: 支持 E2E 测试
4. 选择 Vue 版本
这里我选择:3.x
安装的 vue-cli 将会是基于 vue3.x 版本
5. 是否使用 class 风格的组件语法
如果在项目中想要保持使用 TypeScript 的 class 风格的话,建议大家选择y。
这里我选择:y
6. 是否使用 Babel 与 TypeScript 一起用于自动检测的填充
这里我选择:y
7. 是否使用 history 路由模式
这里我选择:y
8. 选择CSS预处理器
Sass/SCSS分两种:
node-sass:是用 node(调用 cpp 编写的 libsass)来编译 sass,是自动编译实时的
dart-sass:是用 drat VM 来编译 sass,需要保存后才会生效
这里我选择:Sass/SCSS(with node-sass)
9. 选择 eslint 配置
ESLint with error prevention only:只进行报错提醒;
ESLint + Airbnb config:Airbnb配置,不严谨模式;
ESLint + Standard config:标准配置,正常模式;
ESLint + Prettier:严格模式;
TSlint:typescript格式验证工具
这里我选择:ESLint with error prevention only
10. 选择什么时候执行 eslint 校验
Lint on save:保存时检查
Lint and fix on commit:提交时检查
这里我选择:Lint on save
11. 选择配置文件存放的位置
In dedicated config files:在专用的配置文件中单独存放
In package.json:存放在 package.json 中
这里我选择:In dedicated config files
12. 是否保存之前的配置项
这里我选择:N
13. 等待下载依赖模块
14. 装好后,进入目录,启动
cd my-project ( 进入项目根目录 )
yarn serve ( 启动项目 )
项目目录
现在的目录是 Vue3.x 的 cli 看上去简洁多了,去掉了 Vue2.x 中 build 和 config 等目录
项目配置
在项目的根目录下新建 vue.config.js 文件(是根目录,不是src目录)
module.exports = {
publicPath: process.env.NODE_ENV === "production" ? "./" : "/", // 部署生产环境和开发环境下的URL
outputDir: 'dist', // 构建输出目录(npm run build 或 yarn build 时 ,生成文件的目录名称)
assetsDir: 'assets', // 用于放置生成的静态资源(js、css、img、fonts)的;(项目打包之后,静态资源会放在这个文件夹下)
lintOnSave: true, // 是否开启eslint保存检测,有效值:ture | false | 'error'
runtimeCompiler: false, // 是否使用包含运行时编译器的Vue核心的构建
transpileDependencies: [], // 默认情况下 babel-loader 忽略其中的所有文件 node_modules,这里可增加例外的依赖包名
productionSourceMap: false, // 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度
filenameHashing: false, //默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存。你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变)
css: { // 配置高于chainWebpack中关于 css loader 的配置
modules: false, // 是否开启支持 foo.module.css 样式
extract: true, // 是否使用 css 分离插件 ExtractTextPlugin,采用独立样式文件载入,不采用