小聂子客栈

vue相关(持续更新01.31)

热度

Vue相关设置和基础用法

零碎集

1. 多个锚点

有时候页面内容过多,要在侧栏做个导航栏:参考地址

2. 监听页面滚动

1
2
3
4
5
6
7
8
9
10
11
12
methods: {
handleScroll(){
console.log("I am scroll !!!")
}
},
created(){
window.addEventListener("scroll", this.handleScroll)
},
destroyed(){
window.removeEventListener("scroll", this.handleScroll)
}
;

3. 图片相对地址

如果用../../assets/example.png插入.vue文件,一旦文件变动,地址可能也要改。所以用vue-loader的转换规则
@build/webpack.base.config.js中可配置

1
<img src="~@/assets/example.png">

ElementUI

1
2
3
4
5
import ElementUI from "element-ui"
import "element-ui/lib/theme-chalk/index.css"
//修改ElementUI默认值
ElementUI.Dialog.props.appendToBody.default = true;
Vue.use(ElementUI);

内容较多,另开文章说明:第一版第二版


VCharts

单个引入

1
2
3
//折线图
import VeLine from 'v-charts/lib/line'
Vue.component(VeLine.name,VeLine);
1
<ve-line :data="chartData" :settings="chartSettings" :extend="chartExtend" :grid="chartGrid" :colors="chartColor0"></ve-line>

所遇到相关问题:不点不知道


Emojify

1
2
3
4
5
6
7
8
9
10
11
12
import Emojify from 'emojify.js'
// import 'emojify.js/dist/css/basic/emojify.min.css'//emoji单个图
import 'emojify.js/dist/css/sprites/emojify.min.css'//emoji雪碧图
Emojify.setConfig({ mode: 'sprite' })//雪碧图模式
Emojify.run()
Vue.prototype.$emoji = Emojify;
// => 栗子
let code = ":rose:",
that = this,
emojify = code.replace(/\:\w+\:/g,(str) => {
return that.$emoji.replace(str)
});

引入自定义组件

1
2
import ReturnBack from '@/components/returnback'
Vue.component('sl-back',ReturnBack);

全局过滤器

1. 时间戳转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Vue.filter("Timer", (val, is_time, is_second) => {
/*
* @param {is_time} Boolean 是否返回时分
* {is_second} Boolean 是否返回秒
*/
if(!val){
return val
}
let stamp = new Date(parseInt(val)),
year = stamp.getFullYear(),
month = (stamp.getMonth()+1 < 10 ? '0'+(stamp.getMonth()+1) : stamp.getMonth()+1),
day = (stamp.getDate() < 10 ? '0'+stamp.getDate() : stamp.getDate()),
hour = (stamp.getHours() < 10 ? '0'+stamp.getHours() : stamp.getHours()),
minute = (stamp.getMinutes() < 10 ? '0'+stamp.getMinutes() : stamp.getMinutes()),
second = (stamp.getSeconds() <10 ? '0' + stamp.getSeconds() : stamp.getSeconds()),
tims = year+"-"+month+"-"+day;
if(is_time){
tims += " "+hour+":"+minute;
tims = is_second ? times+":"+second : times;
}
return times;
});

2. 筛选键值对

1
2
3
4
5
6
7
8
9
10
11
12
13
Vue.filter("ValueToName", (val, list, key, name) => {
/*
@param {list} Array 筛选的列表
{key} String 与val对应的键值
{name} String 返回内容的键值
*/
if(val || val == 0){
let arr = list.filter((v) => v[key] == val);
return arr.length !== 0 ? arr[0][name] : val;
}else{
return val
}
});

=> 栗子

1
<div>{{ params.levelNo | ValueToName(levellist,'levelNo','levelName') }}</div>

3. 手机号码部分隐藏

1
2
3
4
5
6
7
Vue.filter("BlurMobile", (val) => {
if(val.length == 11){
return val.substr(0, 3) + '****' + val.substr(7)
}else{
return val
}
});

4. 数字转换成千分位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Vue.filter("ToThousands", (val) => {
// 转换数字类型
if(typeof val !== 'number' && !isNaN(val)){
val = Number(val)
}
if(!val || val === 0 || isNaN(val)){
return val
}else{
let num = 0;
if(val.toString().indexOf ('.') !== -1){// 带小数点
num = val.toLocaleString()
}else{
num = val.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
}
return num;
}
});

全局指令

1. 限制输入小数位数

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
/*
@directive 输入框限制范围:小数点个数 or 整数
@param {data-index} 如果是数组要加入index
@param {data-dotrange}
*/

let FindElement = (parent, selector) => {
return parent.tagName.toLowerCase() === selector ? parent : parent.querySelector(selector);
}

// 设置组件中的指定属性的值
let setValue = function(exp, value, context) {
value = isNaN(value) ? '' : value
new Function('context', 'value', `context.${exp} = value`)(context, value)
}

let InputNumDigit = {
bind: function(el, { expression }, { context }){
let $input = FindElement(el, 'input');
el.$input = $input;

// 初始化lastValue
$input.lastValue = $input.value

// 通过dataset 判断是否允许小数点
let allowDot = !!$input.dataset.dotrange,
keys = $input.dataset.keys || -1,// 如果是数组则加入索引
dotRange = $input.dataset.dotrange || `{0,2}`, // 默认
pattern = `^[0-9]+${allowDot ? `(.[0-9]${dotRange})?` : ''}$`,
new_expression = expression;
if (!expression) {
throw new TypeError('请绑定expression')
}

// 循环
if(keys !== -1){
new_expression = expression.replace(/\[.*?\]/, `[${keys}]`)
}
console.log(new_expression)

$input.handleInputEvent = function(e) {
setTimeout(() => {
if (e.target.value === '') {
setValue(new_expression, '', context)
// 遇到非法数值,则重置
e.target.value = ''
} else if (e.target.value !== '' && !new RegExp(pattern).test(e.target.value)) {
setValue(new_expression, parseFloat(e.target.lastValue), context)
// 遇到非法数值,则重置为lastValue
e.target.value = e.target.lastValue
if (allowDot) {
// 这个时候,根据业务逻辑,可以收起键盘,给出吐司提示
let num = dotRange.replace(/[}{]/g, '').split(',')[1];
if(num || num === 0){
$input.title = `小数点后最多${num}位`
}
}
}
e.target.lastValue = e.target.value
}, 0)
}
$input.addEventListener('input', $input.handleInputEvent, false)
},
unbind(el) {
el && el.$input.removeEventListener('input', el.$input.handleInputEvent, false)
}
};
Vue.directive('num-digit', InputNumDigit)

=> 栗子:

1
2
3
4
5
<el-input v-model.number="setForm.price"
v-num-digit="setForm.price"
data-dotrange="{0,2}"
type="number"
class="non-arrow"></el-input>

2. 防止按钮重复点击

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const deafultClock = 1000;// 默认可点击时长
let StopDoubleClick = {
inserted: function(el, binding){
el.addEventListener("click", () => {
console.log("———— stop double click ————")
if(!el.disabled){
el.disabled = true
setTimeout(() => {
el.disabled = false
}, binding.value || deafultClock)
}
})
}
};
Vue.directive('stop-dbclick', StopDoubleClick)

=> 栗子

1
<el-button v-stop-dbclick>保存</el-button>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var getCookie = (name) => {
let arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
arr = document.cookie.match(reg);
return arr !== null ? decodeURIComponent(arr[2]) : null;
}
Vue.prototype.getCookie = getCookie;
Vue.prototype.setCookie = (name,val,expir) => {
let _date = new Date();
_date.setDate(_date.getDate() + expir);
document.cookie = name + "=" + encodeURIComponent(val) + ((expir == null) ? "" : ";expires="+_date.toGMTString());
}
Vue.prototype.delCookie = (name) => {
let val = getCookie(name);
if(val !== null){
document.cookie = name + "=" + val + ";expires=Thu, 01 Jan 1970 00:00:01 GMT;";
}
}
// => 栗子
this.setCookie("TOKEN",response.data);
this.getCookie("TOKEN");
this.delCookie("TOKEN");

Vuex

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
import Vuex from 'vuex'
import { Axios } from '@/axios'
Vue.use(Vuex)

let GET_LIST = 'GET_LIST';//定义全局

/* 模块命名空间 */
const Setting = {
namespaced: true,
state: {
userlist: []
},
mutations: {
SET_USER(state, list){
state.userlist = list
}
}
}
export default new Vuex.Store({
state: {
api: {
city: '/city.act'
},
citylist: []
},
modules: {
Setting,
},
mutations: {
[GET_LIST](state, { context, val }){
Axios.get(state.api[val.apiName], val.params).then((response) => {
console.log(response)
if(response.code){
state[listName] = response.data
}
})
}
},
actions: {
[GET_LIST](context, val){
context.commit(GET_LIST, { context, val })
}
}
});
  1. 栗子 => 模块命名空间

    1
    this.$store.commit("Setting/SET_USER", []);
  2. 栗子 => 异步分发

    1
    2
    3
    4
    5
    this.$store.dispatch('GET_LIST', {
    params: {enable: true},
    apiName: 'city',
    listName: 'citylist'
    });

VueRouter

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
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
mode: 'history',//路由模式
base: '/home/',//路由初始位置
/* 控制滚动条位置 */
scrollBehavior(to, from, savedPosition){
if(savedPosition){
return savedPosition
}else{
if(to.hash){//锚点
return { selector: to.hash }
}else{
return { x: 0, y: 0 }
}
}
},
routes: [{
path: '',
name: 'login',
//懒加载 type1
component: (resolve) => require(['@/view/login'], resolve)
},{
path: 'password',
name: 'password',
//懒加载 type2
component: () => import(/* webpackChunkName: 'password' */'@/view/password')
},{
path: 'container',
name: 'container',
component: (resolve) => require(['@/view/container'], resolve),
//控制路由缓存
meta: {
keepAlive: true
},
//控制路由跳转,检测是否已登录
beforeEnter: (to, from, next) => {
if(!localStorage.ACCOUNT || localStorage.ACCOUNT == ''){
next({ name: 'login' })
}else{
next()
}
}
}]
});
  1. 栗子 => 路由缓存

    1
    2
    3
    4
    <keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
  2. 栗子 => 缓存登录信息

    1
    2
    3
    4
    5
    6
    this.$http.post('login.api',userparam).then((response) => {
    if(response.data){
    localStorage.removeItem("ACCOUNT");//删除旧数据
    localStorage.setItem("ACCOUNT",JSON.stringify(userparam));
    }
    });
  3. 添加百度统计

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    router.afterEach((to, from, next) => {
    setTimeout(() => {
    var _hmt = _hmt || [];
    (function() {
    //先清空页面已有的统计连接
    document.getElementById("BaiduStatis") && document.getElementById("BaiduStatis").remove();
    var hm = document.createElement("script");
    hm.id = "BaiduStatis";
    hm.src = "https://hm.baidu.com/hm.js?id";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
    })();
    },0)
    });

Webpack

1. 打包后移除console

in build/webpack.prod.conf.js

1
2
3
4
5
6
7
8
9
10
new webpack.optimize.UglifyJsPlugin({
compress: {
warning: false,//移除warning警告
dead_code: true,//移除没被引用代码
pure_funcs: ['console.log'],//不打包的函数
// drop_debugger: true,//移除debugger
// drop_console: true//移除console,包括报错类型
},
sourceMap: true
});

2. 本机IP可访问项目

in build/webpack.dev.conf.js

1
2
3
devServer: {
host: '0.0.0.0'
};

3. 打包时不包含.map文件

in config/index.js

1
2
3
build: {
productionSourceMap: false
};

4. 第三方组件单独打包DLLPlugin

1. 新增文件

new build/webpack.dll.config.js 参考文章

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
var path = require('path');
var webpack = require('webpack');

module.exports = {
entry: {
vendor: ['vue/dist/vue.esm.js', 'axios', 'vue-router', 'element-ui', 'emojify.js', 'awe-dnd', 'echarts']
},
output: {
path: path.join(__dirname, '../static/js'),
filename: '[name].dll.js',
library: '[name]_library'
},
plugins: [
new webpack.DllPlugin({
path: path.join(__dirname, '.', '[name]-manifest.json'),
name: '[name]_library',
context: __dirname
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
dead_code: true,//移除没被引用的代码
pure_funcs: ['console.log']//发布时不被打包的函数
}
})
]
}

2. 新增插件

in build/webpack.dev.conf.js and build/webpack.prod.conf.js

1
2
3
4
5
6
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./vendor-manifest.json')
})
]

3. 新增命令

in package.json

1
2
3
"scripts": {
"dll": "webpack --config ./build/webpack.dll.config.js"
};

4. 引入DLL文件

in index.html

1
<script src="/static/js/vendor.dll.js"></script>

5. 打包构建

1
2
npm run dll
npm run dev / npm run build

Vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from 'vue'
import App from './App'
new Vue({
el: "#app",
router,
store,
render: h => h(App),
watch: {
/* 监听路由变化 */
'$route': 'handleRouter'
},
methods: {
handleRouter(){
console.log("路由变化...")
}
}
});
Tags: vue

扫描二维码,分享此文章