我的码云仓库地址
安装elementui npm/cnpm i element-ui -S/--save
在main.js完整引入elementui:
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
将登录页面写过来:点击登录,请求数据,处理数据,获取到token,有token,进入首页
1.npm install axios --save
2.在main.js中引入
import Axios from 'axios'
Vue.prototype.$axios = Axios //将引入的axios挂到原型上
3.在具体组件中的mounted钩子中使用:
mounted: {
this.$axios.get('url')
.then(res => {
console.log(res.data)
})
.catch(error => {
})
}
1,在src新建一个文件夹,生成一个cookie.js文件:
用来封装cookie的set get方法
2.在登录页面引入:
import {
setCookie,getCookie} from '@/utils/cookie.js'
//使用set get方法 存储数据给cookie,取数据
1 路由拦截:
在需要进行登录验证的路由设置meta: {
requireAuth:true}
利用vue-router提供的钩子函数beforeEach()对路由进行判断 写在路由入口文件
2 axios拦截器:
//在路由拦截中,只要需要登录验证并且token存在就可以进入首页。
//如果token失效了但它依然存在,也可以进入首页,不允许这样的情况出现,所以需要axios拦截。
如果token存在就把token写进请求头
【相当于将token状态发送给后台】,后台会给返回值告诉前端token是否失效,如果失效就回去登录页面
1 npm install iview --save
2 为了统一iview标签的书写规范,安装iview loader
npm install iview-loader --save
3 在main.js中引用并注册iview:
import iView from 'iview'
import 'iview/dist/styles/iview.css'
Vue.use(iView)
4 修改webpack配置:
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: vueLoaderConfig
},
{
loader: 'iview-loader',
options: {
prefix: false
}
}
]
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
}
npm i babel-plugin-import -D
在 babel.config.js 中配置
module.exports = {
plugins: [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
}
npm i vant -S
// 插件会自动将代码转化为按需引入形式
import {
Button } from 'vant'
引入vant后可以在方法中引用轻提示:
function () {
this.$toast({
message:'登录成功',
})
}
//cmd定位到项目根目录,
//vue ui安装babel-plugin-import依赖
//再重启项目npm run serve
E:\自学代码\VUE\companypro\permissionsys>vue ui
Starting GUI...
Ready on http://localhost:8000
1,npm i vuex -S
2.在main.js导入包 import Vuex from 'vuex'
3.在main.js注册vuex到vue中: Vue.use(Vuex)
4.在main.js 中new一个vuex实例,得到一个数据仓储对象
const store = new Vuex.Store({
//每个应用只有一个store实例,包含了全部的应用层级状态,单一状态树
state: {
//存储数据 这里存储的数据,可以全局使用,所有组件都可以使用 $store.state.count
count: 0
},
mutations: {
//通过调用mutations的方法去操作state的数据,强烈不推荐直接操作state中的数据,容易造成数据紊乱,无法快速定位到错误源
increment(state) {
//通过increment方法操作state中的count数据 子组件如果想要操作count数据就去调用increment方法 this.$store.commit('方法名')
state.count++;
}
},
getters: {
//只负责对外提供数据,不负责修改数据 $store.getters.optCount 把原数据做一层包装,提供给调用者
//只要state中的数据发生变化了,如果getters也正好引用了数据,就会理解触发getters的重新求值
// optCount: function(state) {
// return '当前最新的count值是:'+state.count
// }
}
})
5,把store挂载到vm实例中 所有子组件能通过this.$store访问到
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
this.$store.state
来获取,数据不能通过state直接修改,改是可以改但是容易出错,也不符合vuex原理this.$store.commit('方法名称',唯一的一个参数)
】,$store.getters.方法名
#this.$emit(‘父组件中的方法名’)
start nginx 启动
修改nginx.conf配置文件,
nginx.exe -s reload重启,
localhost打开页面显示welcome to nginx 或者人去管理器查看进程有nginx说明启动成功。
添加链接描述
module.exports = {
runtimeCompiler: true,
devServer: {
port: 8080,
host:"127.0.0.1",
open:true,
proxy: {
'/api': {
//请求的接口地址是以/api开头的,就会走该代理
// ws:false,
target: 'http://192.168.91.4:8088/pms', //后端接口地址
secure: false, //如果是https接口,需要配置这个参数
changeOrigin: true, //是否允许跨越
pathRewrite: {
//重写
'^/api': 'api'
}
}
},
}
}
{
//在watch不应该使用箭头函数,因为箭头函数绑定了父级作用域的上下文
//1 当值发生改变时触发 监听data数据的变化
//2 监听非dom元素的变化,比如监听路由地址的变化 this.$route.path
// '$store.state.count': function() {
// console.log('监听到了count属性值的变化')
// },
// '$route.path': function(newVal, oldVal) {
// // console.log('new: %s, old: %s',val,oldval)
// // if(newVal==='/index') {
// // console.log('当前是首页')
// // }
// console.log(newVal+'-----'+oldVal)
// },
// treedata: {
// function(newVal, oldVal) {
// alert('输出接口数据===========');
// this.treedata = newVal;
// console.log(this.treedata+oldVal);
// },
// immediate: true, //表示在watch里声明了treedata就会立即执行里面的handler方法
// }
},
当多次调用计算属性时,因为存在缓存,不会多次执行。
而方法每调用一次执行一次。
computed: {
//计算属性 本质上是方法,但直接把名称当成属性来使用,不会当成方法去调用
//1 计算属性在引用的时候直接引用名称,不加()
//2 只要计算属性function内部用到了data中的数据并且数据发生变化,就一定会重新计算该计算属性的值
//3 计算属性的求值结果会被缓存起来,方便下次直接使用;
//4 在计算属性内部的函数,都需要return一个值,在watch中不需要return
},
// this.$axios({
// method: 'get',
// // url:'http://192.168.91.4:8088/pms/Resource/getResourceTree',
// url:'http://192.168.91.4:8088/pms/Resource/getMenuPer',
// headers: {
// "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
// }
// })
// .then(res => { // 请求发送成功的操作
// // alert('请求发送成功')
// //获取到接口数据
// // console.log("=====请求菜单接口成功拿到的接口数据======")
// console.log(res.data);
// if(res.data['code'] == 1) { //如果code1说明有权限并且能成功拿到数据
// this.treedata = res.data.data
// console.log("2")
// // console.log("=====获取到的接口数据======")
// // console.log(this.treedata)
// }
// else { //登录失败,弹出错误提示
// // alert(data['message']);
// }
// })
// .catch(error => { // 请求发送失败的操作
// // alert('请求发送失败')
// console.log(error);
// });
// this.$axios({ //获取list接口
// method: 'get',
// // url:'http://192.168.91.4:8088/pms/Resource/getResourceTree',
// url:'http://192.168.91.4:8088/pms/Resource/getResourceTree',
// headers: {
// "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
// }
// })
// .then(res => {
// console.log(res.data);
// if(res.data['code'] == 1) { //如果code1说明有权限并且能成功拿到数据
// this.listdata = res.data.data
// }
// else { //登录失败,弹出错误提示
// // alert(data['message']);
// }
// })
// .catch(error => { // 请求发送失败的操作
// // alert('请求发送失败')
// console.log(error);
// })
添加链接描述
@node-click=“handleNodeClick”
节点被点击时,会回调数据。共三个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。
handleNodeClick(data) { //点击节点,获取到节点的子节点数据并将数据传给boddy–>content–>list
alert(“点击事件触发了”);
console.log(data); //data为组件自带的函数的返回值,返回当前节点数据
}
父组件中:<子组件 v-bind:data=“data” />
子组件中:props: {data}
1 原理:父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当作参数传递进去;
2 父组件将方法的引用传递给子组件,其中,getMsg是父组件中methods中定义的方法名称,func是子组件调用传递过来方法时候的方法名称
在父组件中:
<子组件 @func=“getData” />
getData(data) { //拿到子组件传递过来的值
this.sondata = data;
}
在子组件中:
通过this.$emit(‘func’,要传递的数据)的方式来调用父组件的getData方法,同时把数据传递给父组件
{“accountfor”:“注册资源”} =====> [{“accountfor”: “注册资源”}]
var arr = [];
arr.push(需要转数组的数据);
sondata = arr; //将数组赋值给sondata
为了实现点击树菜单,将相应的子节点数据和当前节点数据显示在列表。递归遍历多维数组并解析成一维数组
parseArr: function(arr,res){ //数组扁平化,递归多维数组成一维数组显示
for(var i=0;i
if(arr[i].children){ //如果当前元素是数组
this.parseArr(arr[i].children,res);
}else{
res.push(arr[i]);
}
}
},
将数据在watch中监听:
watch: {
treedata(newVal) { //拿到treedata所有数据,扁平化传给list
var listdata = newVal;//把数据给到listdata
var array = [];
array.push(listdata); //把listdata转数组
var arrdata = [];
this.parseArr(listdata,arrdata); //递归listdata数据并将新生成的一维数组赋值给arrdata
listdata = arrdata;
this.$emit(‘func’,listdata); //将listdata传给父组件 父组件种使用sondata来接收这个数据
}
},
getQueryString:function(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
var r = window.location.search.substr(1).match(reg);
if (r != null) {
return unescape(r[2]);
}
return null;
}
created() {
var tok=this.getQueryString('token');
console.log(this.getQueryString('token'));
if(tok!==null&&tok!=='') {
setCookie("X-Access-Token",this.getQueryString('token'),1000*60*30);
}
},
methods: {
getQueryString:function(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
var r = window.location.search.substr(1).match(reg);
if (r != null) {
return unescape(r[2]);
}
return null;
}
}
rowClick(rowIndex){
//点击后的当前行
console.log('点击高亮');
this.id=rowIndex.id;//点击获取当前权限的id
},
/*当前行选中状态下高亮,需要和highlight-current-row="true"配合使用,否则无效*/
.el-table--striped .el-table__botr.el-table__row--striped.current-row td,
.el-table__body tr.current-row > td {
background-color: #2aca76 !important;
}
1,在父组件中重写方法,在父组件中的子组件标签添加ref
https://blog.csdn.net/byfate/article/details/90681625
<iconact_pool ref="myinterface" />
2,在父组件的事件中重写方法:我要在当前行的点击事件中重写
rowClick(row,event,column){
this.$refs.myinterface.del=function() {
}
}
3.在父组件的事件中调用方法,this.$refs.myinterface.del();
#在列表中重写图标组件中的方法, 点击当前行触发方法,虽然可以避免点击图标触发所有行的图标事件,但是却导致,点击当前行的任意位置,都会调用删除图标的事件.思路是,在父组件中定义一个点击删除图标的触发事件,将重写的删除事件在此处引用【无法凭空定义一个触发事件,需要将事件绑定到元素上,在当前行使用插槽,在插槽内添加元素,并绑定方法,当点击该元素的时候触发方法,在该方法内引用子组件的删除事件。这样的话,需要在插槽中写三个按钮,在list写三个方法,分别引用子组件的三个方法。而且这三个元素不应该显示出来被看到,那么就无法实现点击。所以有了思路2】。思路2是===将图标操作提到和列表组件同级显示,直接通过图标的点击事件去触发事件。得到解决。【但是权限维护的弹框没有显示,并且,如何实现点击编辑图标后,当前行由只读属性变为可编辑属性,插件中暂未找到相似的属性;这样的显示方式,就不需要当前行的事件获取id并传值,图标的事件可以直接获取到当前行的所有数据,可以直接对数据进行处理并请求】
https://www.cnblogs.com/shj-com/p/8779965.html
del(row) {
console.log(row.id)
}
#传参时请求头出现content-type为text/plain的问题 修改post请求头的content-type??数据不进行stringify转换,请求头数据格式默认是json也不用设置,设置不设置都没影响
https://blog.csdn.net/weixin_40402192/article/details/83178442
参数转换写在axios前面。请求头设置在拦截器里,然后在后面的所有请求接口都不需要设置请求头了
#尝试设置树菜单的最大高度与列表最大高度一致,未找到类似属性,js操作dom去改变??
#重写后的权限池列表,将图标写在插槽,popover弹框无效??
#https://www.jianshu.com/p/53deecb09077
get请求传参用params,delete用data
#角色管理的列表请求 数据返回参数为空 新增请求
角色新增成功后为什么返回数据为空 传参页码返回数据也为空
列表请求与新增请求同时触发的问题
#权限池的编辑,搜索,角色管理的列表,都待完善。
#插槽里使用插槽的踩坑
#所有get没有content-type属性,使用params接收参数,会自动转换数据格式,不需要手动stringify post需要转,有请求头设置
https://www.cnblogs.com/weijiutao/p/10956808.html
#点击编辑当前行
https://blog.csdn.net/u013466380/article/details/84941658
#点击编辑,通过当前行的点击事件拿到当前权限的id和权限名,传给弹框嵌套表单,id需要传给接口,权限名需要在弹框显示 实现
#popover弹框的取消操作
第一步在弹框加入::ref="popover-${scope.$index}
"
第二步在取消按钮添加点击事件:@click=“cancel(scope)”
第三步:
cancel(scope) {//点击取消关闭弹框
this. t o a s t ( / / 权 限 查 看 的 取 消 操 作 m e s s a g e : ′ 已 取 消 ′ , ) s c o p e . s e l f . toast({ //权限查看的取消操作 message:'已取消', }) scope._self. toast(//权限查看的取消操作message:′已取消′,)scope.self.refs[popover-${scope.$index}
].doClose();
},
#文件之间传递数据
一个msg.js文件:
import Vue from ‘vue’
export default new Vue
传递数据:
Msg. e m i t ( ′ 函 数 名 ′ , d a t a ) 接 收 数 据 : M s g . emit('函数名',data) 接收数据: Msg. emit(′函数名′,data)接收数据:Msg.on(‘函数名’,res=>{})
#设置日期选择器在最上面显示
.hh{
z-index:999!important;
top:188px!important;
}
#控制弹框的关闭
方法一:只能关闭一个弹框
:ref="popover-${scope.$index}
"
@click=“close(scope)”
cancel(scope) {//点击取消关闭弹框
this. t o a s t ( / / 权 限 查 看 的 取 消 操 作 m e s s a g e : ′ 已 取 消 ′ , ) s c o p e . s e l f . toast({ //权限查看的取消操作 message:'已取消', }) scope._self. toast(//权限查看的取消操作message:′已取消′,)scope.self.refs[popover-${scope.$index}
].doClose();
},
方法二:可以关闭多个弹框 多个弹框的关闭事件的关键在于==:ref="popover--
“中``里面的内容不能重复
1 :ref=”popover--
"
2 @click=“cancel()”
3 close() {
this.$refs[popover--
].doClose();
}
4 cancel() {
this.close();
}
#刷新当前页面,局部刷新:
1.在父页面:
export default{
provide() {
return {
reload:this.reload
};
},
data(){
return {
isRouterAlive:true
}
},
methods:{
reload() {
this.isRouterAlive = false;
this.$nextTick(function() {
this.isRouterAlive = true;
})
}
}
}
2.在需要刷新的子页面:
export default{
inject:[‘reload’], //导入reload
}
3.在需要执行的地方直接调用 this.reload()
#当列表中每一行都有下拉框时,如何给每个下拉框都传应用程序数据 目前只能给第一行的下拉框传值,其他行拿不到数据
#使用v-if新增和删除组件 https://www.jianshu.com/p/4c5bdd3b323e
Vue.component(‘HelloWorld’, {
template: ‘#helloworld’,
created() {
console.log(‘helloworld created!’)
},
destroyed() {
console.log(‘helloworld destroyed!’)
},
})
var app = new Vue({
el: ‘#app’,
data: {
showHelloWorld: true
}
})
#点击模块级复选框动态创建删除组件 或者动态创建删除html 给每个复选框都绑定showCheck属性,showCheck控制html的显示隐藏
给每个复选框绑定V-bind:showCheck
给html盒子通过v-if判断显隐
#v-for 循环动态绑定数据 v-model绑定
https://blog.csdn.net/weixin_44724060/article/details/88146731
{ {value.accountfor}}-{ {index}}
{ {value}}
#元素的属性绑定以及html的绑定
https://www.jianshu.com/p/fee0104eadc5
#组件的绑定创建和删除
// Vue.component(‘checkboxes’,{
// template:’#checkboxes’,
// created() {
// console.log(‘checkboxes created’);
// },
// destroyed() {
// console.log(‘checkboxes destoryed’);
// },
// })
v-bind:showCheck=“true”
#v-for 嵌套v-for的v-model属性绑定问题
https://blog.csdn.net/qq_40101922/article/details/82347632
#当在组件中使用v-for的时候,key属性是必需的
#https://www.cnblogs.com/yysbolg/p/9876276.html v-model在input的用法
#el-checkbox的一些坑 https://blog.csdn.net/qq_33769914/article/details/81324267?utm_source=blogxgwz0
#天气插件 http://tianqi.2345.com/plugin/setting.htm?style=classicSmall3day
#弹框位置和偏移量
#:modal-append-to-body=“false” 让dialog在最上层显示
#:close-on-click-modal=“false” 点击弹出层以外区域时阻止弹框关闭
#color=“transparent” 设置颜色透明
#判断数组中是否包含某值
arr.indexOf(data) 如果存在data就会返回data的索引 如果不存在就会返回-1
https://www.cnblogs.com/zzsdream/p/11592309.html
if(ids.indexOf(config)!==-1){//如果属于子数据
#深拷贝浅拷贝
https://juejin.im/post/5b5dcf8351882519790c9a2e#heading-2
JSON.parse(JSON.stringify(arr));深拷贝对象 要求arr中不能包含函数对象,因为此方法不能处理函数,如果使用这个方法拷贝带有函数的数据会造成备份数据的函数部分丢失 这样赋值处理的数据不会影响其他数据
#localStorage
存储:window.localStorage.setItem(‘key’,JSON.stringify(Object));
读取:window.localStorage.getItem(‘key’);
删除:window.localStorage.removeItem(‘key’);
清空:window.localStorage.clear();
#el-checkbox文字和复选框的点击事件分开触发
#嵌套循环,内层循环不执行的问题
foreach 不需要循环条件直接一个个遍历出所有数据,最好不要通过foreach对数据进行处理,remove/add或者修改数据。当使用foreach来迭代访问数组元素时,foreach中的循环变量相当于一个临时变量,系统会把数组元素依次赋给这个临时变量,而这个临时变量并不是数组元素,它只是保存了数组元素的值。因此,如果希望改变数组元素的值,则不能使用这种 foreach 循环。https://blog.csdn.net/sx_while/article/details/89299397?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
#数组去重总结 https://juejin.im/post/5b041fa4f265da0b722b774b
#prototype Array.prototype
#https://github.com/sunyongjian/blog/issues/18 循环总结 迭代器
forEach用来遍历数组==简洁,但不能中断跳出循环;
for(var key in obj) 用来遍历对象/数组(可以遍历,不适用),可以获取对象的Key值,只能提取key,value值需要obj[key]访问;
for(var item of arr) 用来遍历集合类型和字符串,但是对象不行;
http://gaoupon.github.io/2016/08/04/ES6-Iterator/
#el-tree让父子节点之间不关联
check-strictly true互不关联,只会改变当前节点的勾选状态/false父子节点之间关联,父节点勾选,子节点一定会勾选,子节点勾选,父节点也会勾选
#数组合并
concat() 连接多个数组,生成新数组,原数组不会改变—效率低,内存浪费
for循环 性能高,但会改变数组本身的值
map() 性能高,会改变数组本身的值
apply() arr1.push.apply(arr1,arr2) 遍历arr2,push合并,会改变数组本身的值
#数组遍历并删除自己
有效方式:使用for(var i = 0 ;i < arr.length;i++){
if(){
arr.splice(i,1);
i–;//如果不改变下标,将会漏掉一个元素 为什么呢?
}
}
#将对象转数组
let arr = [];
for(let i in data){//将对象转数组
this.$set(arr,i,data[i]);
}
console.log(arr);
#@click.native 给子组件绑定原生事件,当父组件引入子组件后,如果要触发子组件的点击事件,直接使用@click不会触发事件,需要@click.native才会触发 相当于把子组件中的方法传给父组件让父组件中可以触发 如果给router-link添加事件的话,需要添加.native,事件才会触发!
当用了封装组件的话,使用按键修饰符需要添加.native才会触发
#@click.prevent 阻止事件的默认行为
百度一下 //阻止a标签跳转,仅执行函数test4()
#@click.stop 阻止事件冒泡
#@click.self 事件触发时判断是否是self
#@keyup.enter 键盘按下enter键时触发
#强制对属性重新赋值/动态修改对象的属性值 value.checked = !value.checked; 容易遇到坑,有时候可以赋值,有时候不行 ,为什么,怎么解决。???
#自动刷新页面,局部刷新页面 https://www.jb51.net/article/14397.htm
#js实现屏幕自适应
window.onload = function () { //加载页面的时候就执行 屏幕自适应
var tensor_obj = document.getElementById(“login”); //根据ID获取html元素
var heigth_screen = window.screen.height; //获取整个屏幕的分辨率
var width_screen = window.screen.width;
// heigth_screen = heigth_screen * 0.85; //在这里分配整个界面的85%给iframe来显示嵌套的界面
tensor_obj.style.height = heigth_screen + “px”;
// width_screen = width_screen * 0.85;
tensor_obj.style.width = width_screen + “px”;
}
v-bind:style=" {height:fullHeight+‘px’,width:fullWidth+‘px’}"
mounted() {
this.fullHeight=document.documentElement.clientHeight;
this.fullWidth=document.documentElement.clientWidth;
},
#js代码执行顺序
https://www.jb51.net/article/127025.htm
#跨域问题 为什么会产生跨域 什么是跨域 跨域的种类有哪些 分别会造成什么影响 分别需要怎么解决 多了解方法 争取找到最优解
https://www.cnblogs.com/yongshaoye/p/7423881.html
#html将图片转base64
https://www.sojson.com/image2base64.html
#js对象赋值的问题 深拷贝浅拷贝问题 赋值不成功/ 赋值影响原始数据/赋值丢失数据 /赋值改变数据类型等?
https://blog.csdn.net/weixin_33699914/article/details/88624156
#背景图片大小屏幕自适应
https://www.cnblogs.com/xjd-6/p/10931061.html
background: url(’…/assets/app.jpg’) no-repeat;
/* 让整个div固定在屏幕的最上方和最左方*/
position: fixed;
top: 0;
left: 0;
/* 让整个div跟屏幕大小尺寸一样 /
width: 100%;
height: 100%;
/ 让div层级在最下面 /
z-index: -10;
zoom: 1;
/ 让图片随屏幕大小同步缩放 /
background-size: cover;
-webkit-background-size: cover;
-o-background-size: cover;
/ chrom/opera兼容 */
background-position: center 0 ;
#局部高度自适应 比如页面内的列表高度随着屏幕大小自适应宽高
#清除路径上的参数
https://blog.csdn.net/qq_38906555/article/details/82688586
let url = window.location.href;//当前页面路径 http://hcfasys.cn:9090/home?token=…
// let urlparams = window.location.search.substr(1);//页面参数 token=…
let beforeurl = url.substr(0,url.indexOf(’?’));//页面主地址,参数之前的地址 http://hcfasys.cn:9090/home
url = beforeurl;
// let arr = new Array();
// if (urlparams != “”) {
// let urlParams = urlparams.split("&"); //将参数按照&符分成数组
// for (let i = 0; i < urlParams.length; i++) {
// let paramArr = urlParams[i].split("="); //将参数键,值拆开
// //如果键雨要删除的不一致,则加入到参数中
// if (paramArr[0] != paramKey) {
// arr.push(urlParamArr[i]);
// }
// }
// }
// if (arr.length > 0) {
// nextUrl = “?” + arr.join("&");
// }
// url = beforeUrl + nextUrl;
// return url;
#el-tree 横向纵向滚动条
https://www.wandouip.com/t5i392382/
#判断两个数组是否相等
https://www.jb51.net/article/174012.htm
JSON.stringify(arr1)==JSON.stringify(arr2)
1,如果两个数组类型相同,排序相同,JSON.stringify会相等;
2,如果两个数组类型不同,排序相同,用toString结果相等;
3,如果两个数组排序不同,类型相同,sort()从大到小排序,再JSON.stringify,结果相等;
#js如何让键盘回车事件只在当前页面时触发,假如一个项目中的多个页面有多个不同的回车事件呢?
#this. r o u t e 和 t h i s . route和this. route和this.router的区别
https://blog.csdn.net/u014395524/article/details/88194842?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
#让回车事件只在当前页面生效。
1,通过this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …nsole.log(that.router);
// console.log(that. r o u t e ) ; / / l e t u r l = t h a t . route); // let url = that. route);//leturl=that.route.path;
// if(url==’/role’){//如果当前路径是login_user,就执行回车登录
// console.log(‘role’);
// that.onSubmit();//如果输入搜索条件后没有移除光标,回车会全局刷新,需要阻止el-form的全局刷新
// }
// }
// }
2,将事件绑定在DOM元素上:
[email protected]写在el-form上,阻止表单的默认行为(默认刷新);
--------在input上绑定回车事件,@keyup.enter.native=“onSubmit” ,加native表示阻止input的默认行为(默认回车全局刷新),并回车触发onSubmit事件
------在button绑定点击事件,@click=“onSubmit”
这样就能实现:在相应页面触发相应的回车事件,互不影响,并且不会发生表单或者input框的默认回车全局刷新问题。
#js对象转数组
https://www.cnblogs.com/ll15888/p/11993334.html
#el-tree使用default-checked-keys属性,通过一个id数组赋值,设置树的复选框勾选状态。但删除选中状态的话,清空数组是无效的。数组的数据被删除无法直接反应在复选框取消勾选上。使用组件提供的this. r e f s . t r e e . s e t C h e c k e d K e y s ( [ ] ) ; 来 取 消 勾 选 t h i s . refs.tree.setCheckedKeys([]);来取消勾选 this. refs.tree.setCheckedKeys([]);来取消勾选this.nextTick() dom更新之后再执行回调
#路由守卫函数
https://www.jianshu.com/p/5107cb6c21e0
#van-tabs设置当前路由高亮必需是Number类型,否则设置无效
#字符串转数组:
#字符串转布尔:
// stringToBoolean: function(str) {//字符串转布尔
// switch(str) {//toLowerCase把字符串转化写
// case “true”: case “yes”: case"1":return true;
// case “false”: case “no”: case"0":case null: return false;
// default: return Boolean(str);
// }
// }
#模糊查询,判断一个字符串中是否包含某个子字符串
str.match(sonstr) 如果包含会返回数据,如果不包含会返回null
#清空页面html元素 .remove() 或者隐藏hide() 通过document.getEle…调用
#子组件自适应容器高度,并设置最大高度,超出部分出现滚动条
#InfiniteScroll 无限滚动 elementui
#在创建一个Vue 3 的项目时,默认会给出两个环境:
1、development(开发环境):
对应的是 “serve”: “vue-cli-service serve” ,也就是当执行 npm run serve 所运行的环境
2、production (发布环境):
对应的是 “build”: “vue-cli-service build” ,也就是当执行 npm run build 所运行的环境
#Vue CLI 环境变量和模式 https://blog.csdn.net/qq_35366269/article/details/100334104
#解决头像闪烁问题 ???
#Vue.prototype.方法名 = function() {}; 在main.js挂载全局方法
#el-tree改变悬浮样式和选中状态样式
#el-table批量删除
1.
width=“55”
#el-table表格行号
#vue嵌套组件的生命周期 嵌套关系:A>B>C
https://juejin.im/post/5c80bd32518825407505f8bb
beforeCreate: Root
created: Root
beforeMount: Root
beforeCreate: A
created: A
beforeMount: A
beforeCreate: B
created: B
beforeMount: B
beforeCreate: C
created: C
beforeMount: C
mounted: C
mounted: B
mounted: A
mounted: Root
===beforeCreate、created、beforeMount是由外到内,由父到子,顺序执行;
====mounted执行顺序是由子到父。
所以如果子组件给父组件传值的话,一定要在mounted传递数据。
如果父组件在created中接收,会存在先执行父组件的created再执行子组件的mounted或created,导致取不到值的问题。
destroyed====vue中生命周期的销毁函数。实例销毁后调用。常用来销毁一些监听事件和定时器。
#项目文件结构
components放公用组件 多个地方都需要使用到的组件
container全都是重复的或者失效的或者暂时不需要的或者用来测试的组件
views存放各个模块的页面信息和登录注册home等组件
#多个页面共用同一个组件 方法一 在router-view里添加key控制,这样的弊端是如果router-view里包含其他组件,切换其他组件会让其他组件也重新渲染。这样的问题是导致切换路由会闪烁一下。因为切换后所有钩子函数都重新触发了。
1.app.vue中 必须加上key属性,让每次进入路由时都重新触发钩子函数
computed: {
key() {
// 只要保证 key 唯一性就可以了,保证不同页面的 key 不相同
// console.log(this. r o u t e . f u l l P a t h ) ; r e t u r n t h i s . route.fullPath); return this. route.fullPath);returnthis.route.fullPath
}
},
2.在index.js文件中: 让多个路由共同同一个组件,保证path和name属性具有唯一性 。
{
path: ‘/role’,
name: ‘role’, //角色
meta: {
requireAuth: true //表示该路由需要登录验证后才能进入 在切换路径跳转路由之前作判断
},
component: () => import(’@/views/policy/policy.vue’),
// children: [//新增和编辑使用同一个组件,但name必须不同。
// {path: ‘createrole’, component: form_role, name: ‘创建角色’},
// {path: ‘editrole’, component: form_role, name: ‘编辑角色’},
// ]
},
{
path: ‘/strategy’,
name: ‘strategy’, //策略
meta: {
requireAuth: true //表示该路由需要登录验证后才能进入 在切换路径跳转路由之前作判断
},
component: () => import(’@/views/policy/policy.vue’),
},
#多个页面公用同一个组件时:通过以上方法,会让router-view下的所有子组件都重新渲染,影响性能。还可以用第二种方法:通过监听路由的变化,来重写初始数据
参考 【https://www.dazhuanlan.com/2020/01/06/5e12c0b14066b/?cf_chl_captcha_tk=15752335c3e03d19df46231178225127e7dbb184-1588051351-0-AX69UpKqo9ice-NLT0mXfSRSbGP6hix_qGjzKbhdezY8rZXHgxUARbsX5rf5El9k0820ALN6sGcEsMPN1MNQVdBVolkWsu_XTFPJAZR5VYxPTJ75BjiAkzY89S-O_HWB_Ct-5q-CFalYsL4Qvpg7upyb2JkDnB0mEQW0VJPIjFWN2l2evj5eLmJfcKgyqM4GcE5ojEsGpSYsumYOo5GtI-Dez-iG5ip9CWxxOLYlEQaOPvkn48WVED78AuUgO7VHpZ6hW4fQR8k7fSH7-bGUcv9OmN7uhw9PGJtngsA1v4NDgYB_Dsbfl0FaN6it9yOAqyw0eprclySD8I8yiO5F6uKPG9qpMuxpo7cCbPtE3iaA】
//监听$route的变化来初始化数据 当多个组件公用同一个组件时,切换路由不会重新触发钩子函数。可以通过监听路由的方法或者router-view添加唯一key值的方法来重新触发钩子函数
1.
watch: {
KaTeX parse error: Expected 'EOF', got '}' at position 48: …Data', } }̲, 2. methods:{ …route.fullPath==’/strategy’||this.$route.fullPath==’/role’){
方法体
}
}
#el-tab-pane当切换标签的时候如何重新触发子组件的钩子函数?
1:给每个子组件绑定一个isUpdata属性,用来在点击切换的时候控制相应标签页组件是否重新渲染
2.
return{
activeName: ‘role’,//根据用户的点击,会自动改变activeName的值
isUpdatarole:false,
isUpdatastrategy:false
}
3.
methods: {
handleClick(){//控制点击tab时,让子组件重新渲染
if(this.activeName == ‘role’){
this.isUpdatarole = true;
this.isUpdatastrategy = false;
}
else if(this.activeName == ‘policy’){
this.isUpdatarole = false;
this.isUpdatastrategy = true;
}
}
},
#router-link传递参数 https://blog.csdn.net/qq_35393869/article/details/80251099
1.
2.
// console.log(this. r o u t e . q u e r y . u r l ) ; / / c o n s o l e . l o g ( t h i s . route.query.url); // console.log(this. route.query.url);//console.log(this.route.query.id);
#this.KaTeX parse error: Expected '}', got 'EOF' at end of input: …rams:{url:this.route.fullPath,id:row.id}});//this.$route.params.取值
https://blog.csdn.net/qq_40851816/article/details/80695124
#兄弟组件之间传值 没有直接的传值方式,可以通过路由传值,router-link传值 this.$router.push传值
#离开路由时执行的钩子函数 【只有当使用keep-alive时才有效 不对 】这是页面消失时执行的路由守卫函数 与mounted函数同级
deactivated:funtion() {
this.isshow = false;
}
},
#待所有数据全部请求完毕后,再渲染页面,请求数据时页面转圈圈
方法一:表格等局部内容区域加载
.el-table 加载
:data=“data”
v-loading=“loading”
方法二:全屏页面加载
#进入当前路由之前的钩子函数 beforeRouteEnter此时还没有this 路由守卫
https://www.cnblogs.com/huihuihero/p/12133670.html
beforeRouteEnter(to, form, next) {
next()
},
beforeRouteEnter不能访问this如何处理?
可以通过next回调,通过vm访问组件实例
beforeRouteEnter (to, from, next) {
next(vm => {
// beforeRouteENnter不能通过this访问组件实例,但是可以通过 vm 访问组件实例
console.log(vm.permidata) //vm.demodata即this.demodata
})
}
#路由监听:
方法一:全局监听 所有路由发生切换时,都会触发该监听方法collect()
1.
watch:{
KaTeX parse error: Expected 'EOF', got '}' at position 39: …collect' } }̲, 2, methods: {…route":{
handler(route){
const that=this;
if(route.name==‘Hello’){
that.fetchData();
}
}
}
},
2,
methods: {
fetchData() {
有效代码段
},
}
#兼容IE浏览器
1、 安装插件babel-polyfill
【主要针对不兼容ES6新语法的浏览器】
npm install --save-dev babel-polyfill
2、在你的VUE项目的src目录下找到main.js
添加下面一行代码:
import ‘babel-polyfill’
3.最后,重新打开浏览器,应该就能兼容打开页面了。
#兼容问题考虑:
1 vue 只兼容ie8以上版本;
2 IE 不兼容 axios的promiss对象;
3 IE 不兼容es6语法;
4 IE不支持sessionStorage
5 解决兼容性问题:将ES6转ES5
转换语句:npm i babel-preset-es2015
并且在项目的根目录下,修改.babelrc的内容,添加’es2015’
#解决浏览器兼容性 IE
https://blog.csdn.net/qq_24985715/article/details/93764818?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase
#关于解决es6-promise在浏览器的兼容性
1、说明:若在项目中使用了ES6 promise对象,它在Chrome、Safari浏览器下可以正常运行,但在360兼容模式、IE内核中不支持;
2、安装:npm install es6-promise;
3、配置:在main.js中加入require(‘es6-promise’).polyfill(),用于在node或浏览器中支持ES6 与CommonJS。
#事件代理/事件委托 捕获/冒泡 https://www.jianshu.com/p/593ac34a3826
原理:利用事件冒泡,把事件监听绑定到其父容器上
应用场景:页面上又新增的元素,且新增的元素也需要绑定事件时。
#正则 判断字符是否全是中文 form_pool
var isChinese = (rule, value, callback) => {
let regg = /3+$/;
if(!regg.test(value)){
callback(new Error(‘权限名称必须是中文’));
}else {
callback();
}
};
#html每个标签都有title属性
#npm install mockjs
slot方式插入前缀/后缀图标:
或者
属性方式插入前缀/后缀图标
\u4e00-\u9fffa-zA-Z ↩︎
\u4e00-\u9fa5 ↩︎
\u4e00-\u9fa5 ↩︎