# vue工作积累

# 1. vue引入图片无法加载问题

在vue的js引入图片,就需要使用require(“路径”)进来 - <img :src=" require('../../assets/images/url/icon' + (index+1) + '.png') " alt="">

# 2. vue中拖拽

# 2.1. 自定义指令 - 拖拽

<!-- 自定义指令绑定元素 -->
<button v-drag>拖拽</button>
1
2
export default {
    name: "",

    // 自定义指令 - 拖拽
    directives:{
        drag(el, bindings){
            el.onmousedown = function(e){
                var disx = e.pageX - el.offsetLeft;
                var disy = e.pageY - el.offsetTop;
                document.onmousemove = function (e){
                    el.style.left = e.pageX - disx+'px';
                    el.style.top = e.pageY - disx+'px';
                }
                document.onmouseup = function(){
                    document.onmousemove = document.onmouseup = null;
                }
            }
        }
    },
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 2.2. 通过事件触发 - 拖拽

<div class="xxclass" ref="xxref" @mousedown="mouseDownHandleelse($event)" @mouseup="mouseUpHandleelse($event)"></div>
1
export default {
  name: 'zhinengjifang',
  data () {
    return {
      moveDataelse: {
        x: null,
        y: null
      }
    }
  },
  mounted () {
  },
  beforeDestroy () {
  },
  components: {
  },
  methods: {
    mouseDownHandleelse (event) {
      this.moveDataelse.x = event.pageX - this.$refs.xxref.offsetLeft
      this.moveDataelse.y = event.pageY - this.$refs.xxref.offsetTop
      event.currentTarget.style.cursor = 'move'
      window.onmousemove = this.mouseMoveHandleelse
    },
    mouseMoveHandleelse (event) {
      let moveLeft = event.pageX - this.moveDataelse.x + 'px'
      let moveTop = event.pageY - this.moveDataelse.y + 'px'
      this.$refs.xxref.style.left = moveLeft
      this.$refs.xxref.style.top = moveTop
    },
    mouseUpHandleelse (event) {
      window.onmousemove = null
      event.currentTarget.style.cursor = 'move'
      console.log('鼠标松开了')
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.xxclass{
    height: 200px;
    width: 400px;
    position: fixed;
    top: 150px;
    left: 550px;
    cursor: pointer;
}
1
2
3
4
5
6
7
8

# 3. 在eslint模式下,全局变量报错

/* global qs */
console.log(qs.stringify(this.loginForm));
1
2

# 4. vuex存储对象基本用法

// 主入口文件/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import getters from './getters'

Vue.use(Vuex)
const store = new Vuex.Store({
    modules: {
        user,
    },
    getters,
})

export default store

// store.js
const user = {
    state: {
        userRes: {},  // 存储登陆后用户值
    },

    mutations: {
        // 获取登录后用户信息
        SET_USER_RES: (state, userRes)=> {
        state.userRes = userRes;
        }
    }
}

// vue组件中
const userInfo = res.data.data;

// 将用户信息存入vuex中
this.$store.commit('SET_USER_RES', userInfo);

console.log(this.$store.state.user.userRes);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 5. element 有搜索框input筛选的树形菜单

//this.$refs.tree.getCheckedNodes()   //树选中的值
//this.$refs.tree.getCheckedKeys()  //树选中的id
//this.$refs.tree.setCurrentKey(id);//默认高亮
default-expand-all  				--默认展开全部
highlight-current   				--高亮
:filter-node-method="filterNode" 	--筛选input
:expand-on-click-node="false"   	--点击图标才展开
node-key="id"      					--getCheckedKeys必须绑定id
:props="{          					-- 格式化可写在标签内
    label: 'name',
    value:'id',
}"
1
2
3
4
5
6
7
8
9
10
11
12
<div class="tree-box">
    <span class="tree-title">标题</span>
    <el-input
        placeholder="请输入"
        v-model="treeList.filterText"
        suffix-search="el-icon-date">
    </el-input>
    <el-tree
        class="filter-tree"
        :data="treeList.treeData"
        :props="treeList.treeProps"
        default-expand-all
        :expand-on-click-node="false"
        highlight-current
        :filter-node-method="filterNode"
        ref="tree"
        @node-click="treeClick">
    </el-tree>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
data() {
    return {
        treeList:{
            filterText:"",//树形菜单搜索框
            treeData:[],//树形菜单
            treeProps: {         //树形菜单格式化
                label: 'name',
                value:'id',
            }
        },
    }
}
//this.$refs.tree.getCheckedNodes()   //树选中的值
//this.$refs.tree.getCheckedKeys()  //树选中的id
//this.$refs.personTree.setCurrentKey(id);//默认高亮
//树点击
treeClick(data){
    console.log(data)
},
// 过滤树表单内容
filterNode(value, data) {
    if (!value) return true;
    return data.name.indexOf(value) !== -1;
},
watch: {
    // 监听树的搜索框
    'treeList.filterText'(val) {
        this.$refs.tree.filter(val);
    }
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.tree-box{
    width: 268px;
    height: 310px;
    border: solid 1px #e9e9e9;
    border-radius: 4px;
    margin-right: 20px;
    float: left;
    .tree-title{
        display: block;
        color: #666666;
        font-size: 14px;
        background-color: #f1f2f4;
        border-radius: 4px 4px 0 0;
        text-indent: 18px;
        width: 100%;
        height: 40px;
        line-height: 40px;
    }
    .el-input{
        display: inherit;
        margin: 10px auto;
        width: 90%;
    }
    .el-tree{
        margin: 10px auto;
        height: 200px;
        width: 90%;
        /*background: #000;*/
        overflow: auto;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 6. 路由跳转,参数在url

// 跳转页面
jumpPage() {
    this.$router.push({  
    path: '/message-module/approval',  
    // name: 'approval',
    query: {   
        jumpCurr: this.chkApproval.current,   
    }  
    })  
},

if(this.$route.query.jumpCurr !== undefined) {
    this.activeName = this.$route.query.jumpCurr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 7. 在element配置上传文件

<el-upload
        class="upload_wrap"
        ref="upload"
        limit="1"
        :action="uploadUrl"
        :before-remove="beforeRemoveFile"
        :on-exceed="handleExceed"
        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :file-list="fileList"
        :auto-upload="false"
        :on-change="changeFile">
    <el-button slot="trigger" type="text">选取文件</el-button>
</el-upload>

<script type="">
computed: {
    uploadUrl() {
        return (
            "https://jsonplaceholder.typicode.com/posts/"
        );
    },
},

// 文件上传
// 删除文件后操作
handleRemove(file, fileList) {
    console.log(file, fileList);
},

// 删除文件之前的钩子
beforeRemoveFile(file) {
    if (this.isCheck) {
    this.isCheck = false;
    return true;
    }
    return this.$confirm(`确定移除 ${file.name}`);
},

// 限制提示
handleExceed() {
    this.$message.warning(`文件超出上限`);
},

// 点击获取文件信息
handlePreview(file) {
    console.log("点击获取文件信息", file);
},

// 文件改变后触发
changeFile(file, fileList) {
    console.log(file, fileList);
},
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 8. 在element表格编辑

<el-table :data="tableData" border @cell-dblclick="celledit">
<el-table-column type="index" ></el-table-column>

<el-table-column prop="date" label="日期" width="180">
    <template slot-scope="scope">
    <el-date-picker v-if="scope.row.date.edit"
        v-model="scope.row.date.value"
        ref="date"
        style="width: 100%"
        type="date"
        value-format="yyyy-MM-dd"
        @blur="scope.row.date.edit = false">
    </el-date-picker>
    <span v-else>{{ scope.row.date.value }}</span>
    </template>
</el-table-column>

<el-table-column prop="name" label="姓名" width="180" edit="false">
    <template slot-scope="scope">
    <el-input v-if="scope.row.name.edit"
        ref="name"
        v-model="scope.row.name.value"
        style="width: 100%"
        @blur="scope.row.name.edit = false">
    </el-input>
    <span v-else>{{ scope.row.name.value }}</span>
    </template>
</el-table-column>

<el-table-column prop="address" width="260" label="地址">
    <template slot-scope="scope">
    <el-input v-if="scope.row.address.edit"
        ref="address"
        v-model="scope.row.address.value"
        style="width: 100%"
        @blur="scope.row.address.edit = false">
    </el-input>
    <span v-else>{{ scope.row.address.value }}</span>
    </template>
</el-table-column>
</el-table>

<script type="">
data() {
    return {
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄',
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄',
        edit: false
      }],
    }
}

//表格数据格式化成我们想要的数据
/* {
    date: {
    value: '',
    edit: false//编辑状态
    }
} */
formatData(){
    this.tableData.forEach(item => {
    for(let key in item) {
        item[key] = {
        value: item[key],
        edit: false
        }
    }
    })
    console.log(this.tableData)
},
celledit(row, column, cell, event){
    if(row[column.property]){
    row[column.property].edit = true
    setTimeout(() => {
        this.$refs[column.property].focus()
    }, 20)
    }
    
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

# 9. 在vue中compute的值改变,iframe无法渲染

<iframe :src="url" frameborder="0" :key="index"></iframe>

computed: {
    dashboardUrl(){
        return `url`
    }
},

check() {
    console.log("查询", this.filterData);

    this.index++
},
1
2
3
4
5
6
7
8
9
10
11
12
13

# 10. 在js中使用vue router

/*
vue封装的公共方法js中使用router,页面可能报错

可在js中添加
*/

import Router from 'vue-router'
import router from '../router'
Vue.use(Router)
const originalPush = Router.prototype.push
Router.prototype.push = function push (location) {
    return originalPush.call(this, location).catch(err => err)
}

// 引用
router.push('/path')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 11. scss全局使用

css: {
    loaderOptions: {
        sass: {
            prependData: `@import "./src/assets/css/global.scss";`,
        },
    },
},
1
2
3
4
5
6
7

# 12. el-date-picker

<el-date-picker
    v-model="time"
    type="datetimerange"
    range-separator=""
    start-placeholder="开始日期"
    end-placeholder="结束日期"
    value-format="yyyy-MM-dd HH:mm"
    format="yyyy-MM-dd HH:mm" 
    @change="changeTime"
>
</el-date-picker>
1
2
3
4
5
6
7
8
9
10
11

# 13. 带参跳转

// 使用params必须使用name
// 跳转之后页面 url后面不会拼接参数 , 但是刷新页面id 会消失
this.$router.push({
    // path: '/shop/contract/viewContract',
    name: 'viewContract',
    params: {
        handleStatus: '查看'
    }
})
console.log("123", this.$route.params.handleStatus)

// 使用query
// query类似 get, 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传
this.$router.push({
    path: '/shop/contract/viewContract',
    query: {
        handleStatus: '查看'
    }
})
console.log("123", this.$route.query.handleStatus)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 14. el-tree单选

@check="handleCheckChange"

// 单选
handleCheckChange(data) {
console.log(data)
var labvalojb = data; //暂存选中节点
// console.log(data);
this.$refs.sendTree.setCheckedKeys([]); //删除所有选中节点
this.$refs.sendTree.setCheckedNodes([labvalojb]); //选中已选中节点

if(this.subStatus === "single") {}
},

.el-tree .el-tree-node .is-leaf + .el-checkbox .el-checkbox__inner{display: inline-block;}
.el-tree .el-tree-node .el-checkbox .el-checkbox__inner{display: none;}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 15. 根据某个字段合并单元格

export default {
    data() {
        return {
            spanArr: [],//用于存放每一行记录的合并数
        }
    },
    create() {
        // 请求之后
        this.getSpanArr(this.tableData)
    },
    methods: {
        // 表格操作
        getSpanArr(data) {
        // console.log(data)

        // data就是我们从后台拿到的数据
        for (var i = 0; i < data.length; i++) {
            if (i === 0) {
            this.spanArr.push(1);
            this.pos = 0;
            } else {
            // 判断当前元素与上一个元素是否相同
            if (data[i].businessId === data[i - 1].businessId) {
                this.spanArr[this.pos] += 1;
                this.spanArr.push(0);
            } else {
                this.spanArr.push(1);
                this.pos = i;
            }
            }
            // console.log(this.spanArr);
        }
        },
        // 合并 label
        fixTable({ rowIndex, columnIndex }) {
        if (columnIndex === 0 || columnIndex === 1) {
            const _row = this.spanArr[rowIndex];
            const _col = _row > 0 ? 1 : 0;
            // console.log(`rowspan:${_row} colspan:${_col}`);
            return {
                // [0,0] 表示这一行不显示, [2,1]表示行的合并数
                rowspan: _row,
                colspan: _col
            };
        }
        },
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# 16. 重置

  • this.queryParams = this.$options.data.call(this).queryParams

# 17. 监听vuex状态

// store
const state = {
  isFixNav: false
}

const mutations = {
  SET_NAV_FIX: (state, isFixNav) => {
    state.isFixNav = isFixNav
  }
}

const actions = {
  getNavFix({ commit }, isFixNav) {
    commit('SET_NAV_FIX', isFixNav)
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

// layout
import store from '@/store'

let timer = setTimeout(() => {
  let main = document.querySelector('.app-main')
  let nav = document.querySelector('.navbar_wrap')
  // console.log(main, nav)

  // 滚动条监听
  document.addEventListener('scroll', (e)=> {
    console.log(e.target.scrollTop)

    if(!main || !nav) {
      return
    }

    if(e.target.scrollTop > 100) {
      main.classList.add('fixed')
      nav.classList.add('fixed')

      // logo
      store.dispatch('xjp/getNavFix', true)
      // console.log(store.getters.isFixNav)
      // console.log(store)
    } else {
      main.classList.remove('fixed')
      nav.classList.remove('fixed')

      // logo
      store.dispatch('xjp/getNavFix', false)
    }
  }, true);

  clearTimeout(timer)
}, 300);

// vue
import { mapGetters } from 'vuex'

watch: {
    // 监听vux的nav
    isFixNav(val) {
      console.log("123475", val)
      this.navStatus = val
    }
  },
  computed: {
    ...mapGetters([
      'isFixNav'
    ]),
  },

<img src="@/assets/logo/logo1.png" alt="" v-if="!navStatus">
<img src="@/assets/logo/logo.png" alt="" v-else>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

# 18. 国际化表单校验不生效

<template>
  <div id="app">
    <router-view v-if="isActiveRoute" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      isActiveRoute: true
    }
  },
  methods: {
    reload() {
      this.isActiveRoute = false;
      this.$nextTick( () => {
        this.isActiveRoute = true;
      })
    }
  },
  watch: {
    '$i18n.locale'(newVal, oldVal) {
      if(newVal != oldVal) {
        this.reload()
      }
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30