# 再次与vue接触的填坑之路

2018-10-09

vue

# 1. vue中引入json数据

必须创建服务才可以在vue中直接使用json数据;

可参考vue请求本地数据 (opens new window)

下面就本次使用再清晰理一遍:

方法一:

在webpack.dev.conf.js中(vue-cli实现的vue项目框架已经加上理express),直接引入json文件,然后在devServer中加上get或者post请求,然后就可以在vue中正常请求此服务上产生的数据了:

WX20180723-110139.png

var beijingData = require('../beijing.json')

before(app) {
    app.get('/api/beijingData', (req, res) => {
      res.json({
        errno: 0,
        data: beijingData
      })//接口返回json数据,上面配置的数据seller就赋值给data请求后调用
    })
}
1
2
3
4
5
6
7
8
9
10

方法二:

平时我习惯mock.js产生假数据,所以可以用mock的服务来处理json,同样的在vue中就可以正常请求到了。

WX20180723-110139.png

var Mock = require('mockjs');
var beijingdata = require('./beijing.json');
var beijingdata1 = require('./beijing2.json');

Mock.mock('/sinotans/order/leftChart', 'get', function (options) {
    return {
        message: 'success',
        data: { orderNum: beijingdata, goodsAmount: beijingdata1 },
        statusCode: 200
    };
});
1
2
3
4
5
6
7
8
9
10
11

# 2. vue router-link上添加点击事件。

需要添加.native

 <ul v-if="isShow">
    <router-link :to="headNavLink[index]"
        v-for="(item,index) in headNavList"
        :key="index"
        tag="li"
        @click.native="activeChange(index)">
        <div class="nav-icon"></div>
        <span class="nav-font">{{item}}</span>
    </router-link>
</ul>
1
2
3
4
5
6
7
8
9
10

# 3. vue中 watch对象或者数组

vue 实战问题-watch 数组或者对象 (opens new window)

数组和对象都需要深层次监测:

data () {
    return {
        orderTotal: {
            businessSel: '1',
            companySel: '全部',
            projectSel: '全部',
            customerSel: '全部',
            flowFrom: '全部',
            flowTo: '全部'
        },
    }
},
watch: {
    orderTotal: {
        handler(newValue, oldValue) {
            console.log(newValue)
            const businessSelectedw = newValue.businessSel;
            const companySelectedw = newValue.companySel;
            const customerSelectedw = newValue.customerSel;
            const projectSelectedw = newValue.projectSel;
            // 监听 
            if (companySelectedw === '全部') {
                this.projectDisabled = true;
                this.customerDisabled = true;
            } else {
                this.projectDisabled = false;
                this.customerDisabled = false;
            }
            // 监听 
            if ((customerSelectedw !== '全部' && Number(businessSelectedw) === 2) || (projectSelectedw !== '全部' && Number(businessSelectedw) === 1)) {
                this.flowShowFlag = true;
            } else {
                this.flowShowFlag = false;
            }
        },
        deep: true
    }
},
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

如果想监测具体的属性变化,如pokerHistory变化时,才执行handler函数,则可以利用计算属性computed做中间层。

data() {
  return {
    bet: {
      pokerState: 53,
      pokerHistory: 'local'
    }   
    }
},
computed: {
  pokerHistory() {
    return this.bet.pokerHistory
  }
},
watch: {
  pokerHistory(newValue, oldValue) {
    console.log(newValue)
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 4. vue-router多重包含的重定向问题

问题描述: WX20180723-110139.png

我的页面结构是这样的。当时的问题是:在点击四个子页面的时候,内容页一那一层的.router-link-active就没了。后来发现是因为我的内容页和子页面写在同一级别上了(怎么说才对呢————就是我的页面一进入内容页一后我需要直接展示子页面一,而我的内容页一和子页面一的路由写成了一样的,这样就导致子页面和内容页一在同一个里面了。所以就点击子页面时,.router-link-active就只有一个了。在内容页一二上没有了)。解决办法就是内容页一给一个路由,然后重定向到子页面一上。

同时在的子页面二点击按钮处还分为了子页面21和子页面22

export default new Router({
    routes: [
        {
            path: "/",
            redirect: "/index"
        },
        {
            path: "/index",
            component: home
        },
        {
            path: "/pages1",
            redirect: "/pages/childPage1",
        },
        {
            path: "/pages1",
            name: "visualization",
            component: visual,
            children: [
                {
                    path: "/visual/childPage1",
                    name: "orderNumAnaly",
                    component: orderNumAnaly
                },
                {
                    path: "/visual/childPage2",
                    redirect: "/visual/KPI/log",
                },
                {
                    path: "/visual/childPage2/childPage21",
                    name: "KPILog",
                    component: effectKPILog
                },
                {
                    path: "/visual/childPage2/childPage22",
                    name: "effectKPIWater",
                    component: effectKPIWater
                },
                {
                    path: "/visual/childPage3",
                    name: "transWrongAnaly",
                    component: transWrongAnaly
                },
                {
                    path: "/visual/childPage4",
                    name: "visualAbility",
                    component: visualAbility
                }
            ]
        },
        {
            path: "/pages2",
            name: "lot",
            component: lot
        }
    ]
});
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

# 5. amcharts 插件在vue中使用

amcharts必须全局引用,必须在main.js中引用:

官网上的说明 (opens new window)

/* eslint-disable */
import AmCharts from 'amcharts3';
import AmSerial from 'amcharts3/amcharts/serial';
import AmPieChart from 'amcharts3/amcharts/pie';
/* eslint-enable */
1
2
3
4
5

Using amCharts with Vue.js and Webpack (opens new window)

文章最后面说的图标无法显示的问题,如下添加即可:

WX20180723-110139.png

# 6. vue中父组件向路由页传递值

一开始没明白过来router-view上面也可以如同平常组件那样传递props值。所以走了很多弯路。 在此标记:

<router-view :companyOptions="companyOp"></router-view>
1

# 7. props传过来的值作为初始值,后续怎么改变

需求是不需要改变父组件的,只是在父组件中统一请求到了初始值,每个组件中的初始值相同,但后续会不同。

哎呀这次真的被自己坑了:

一开始的思路是知道props不能直接改变的,那就用computed写一个新变量来接收它,然后在方法中改变它,报错没有setter,设置setter不起作用,要不就报错不能修改props,懵了;

问了同事后,才发现简单问题想复杂了。实际上一开始只需要拿到就行了。

data () {
    return {
        op: this.propsValue
    }
},
props: ['propsValue'],
methods: {
    changeOp () {
        this.op = '12334';
    }
}
1
2
3
4
5
6
7
8
9
10
11

# 8. 画图实现的对象上的绑定方法操作本页面数据

问题: 画图的代码在另一个js中封装,本vue中引入js,请求之后调用函数生成myChart对象,即图表对象。此时需要在其上绑定事件。

由于请求是异步执行,所以要考虑保证绑定事件在画图之后。

思路一: 如果在本.vue中等待其后绑定,那么就要使画图代码中return 出去

//setChart.js
import echarts from "echarts";

export default function(data, id) {
    let myChart = echarts.init(document.getElementById(id));
    let option = {};
    myChart.setOption(option);
    window.onresize = myChart.resize;
    return myChart;
};

1
2
3
4
5
6
7
8
9
10
11

在.vue页面:

import myChart from '@/charts/setChart';



mounted () {
    this.utils.MlTools.reqCharts('/sinotans/order/rightChart', 'myChartInit', this.proDym, this)//发起请求画图
},

methods: {
    myChartInit () {
        let data = this.proDym;
        let _this = this;
        myChart(data, "RightChart").on('click', function (params) {
            if (params.componentType === 'series') {
                // 点击到了 markPoint 上
                if (params.seriesIndex === 1 || params.seriesIndex === 0) {
                    _this.tabActive = 1;
                    _this.busCarrier.projectSel = _this.proDym.projectSel;
                    _this.busCarrier.carrierSel = '全部';
                }
            }
        });
    },
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

思路二:传入回调函数

//setChart.js
import echarts from "echarts";

export default function(data, id, callback) {
    let myChart = echarts.init(document.getElementById(id));
    let option = {};
    myChart.setOption(option);
    window.onresize = myChart.resize;
    myChart.on('click', function(params){
         if (params.componentType === 'series') {
            callback();
         }
    })
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在.vue中:

import myChart from '@/charts/setChart';


mounted () {
    this.utils.MlTools.reqCharts('/sinotans/order/rightChart', 'myChartInit', this.proDym, this)//发起请求画图
},

methods: {
    myChartInit () {
        let data = this.proDym;
        myChart(data, "RightChart", this.changeToShip)
    },
    changeToShip () {
        this.tabActive = 1;
        this.busCarrier.projectSel = this.proDym.projectSel;
        this.busCarrier.carrierSel = '全部';
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 9. 后台接收不到数据之content-type

form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded。

当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2...),然后把这个字串追加到url后面,用?分割,加载这个新的url。

当action为post时候,浏览器把form数据封装到http body中,然后发送到server。 如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。 但是如果有type=file的话,就要用到multipart/form-data了。

当action为post且Content-Type类型是multipart/form-data,浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary)。

原生AJAX的POST请求如果不指定请求头Request Header,默认使用的Content-Type是text/plain;charset=UTF-8,参数出现在Request payload块。

一般json数据格式的话,浏览器处就显示的是Content-Type:application/json;chartset=UTF-8

vue中的axios传参方式是request payload,参数格式是json,而并非用的是form传参,所以在后台用接收form数据的方式接收参数就接收不到了。

解决办法:

安装 qs : npm install qs --save

import qs from "qs";
axios({
   method: "post",
   url: param.url,
   dataType: "json",
   data: qs.stringify(param.data),
   headers: {
       "Content-Type": "application/x-www-form-urlencoded"
   },
}).then(res => {
  
}, err => {
   
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 10. axios 实现某些请求的拦截, 不是全局统一拦截

生成实例:

static reqCharts(urls, d, datas, _this, loading) {
        let instance = axios.create();
         // 添加请求拦截器
        instance.interceptors.request.use(function(config) {
            // 在发送请求之前做些什么
            _this[loading] = true;
            return config;
        }, function(error) {
            // 对请求错误做些什么
            return Promise.reject(error);
        });
        // 添加响应拦截器
        instance.interceptors.response.use(function(response) {
            // 对响应数据做点什么
            _this[loading] = false;
            return response;
        }, function(error) {
            // 对响应错误做点什么
            return Promise.reject(error);
        });

       
        return new Promise((resolve, reject) => {
            instance
                .post(urls, datas)
                .then(function(res) {
                    // 处理res
                })
                .catch (function(err) {
                    console.log(err.response)
                })
            })
    }
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

# 11. axios设置请求超时,mock服务下需要设置,否则不起作用。

# 12. vue起服务自动用ip

在config/index.js中,添加:

const ip = require('ip').address();
....
host: ip
1
2
3