假如说有如下的需求: input的value部分有用,部分无用,我们希望input框获取焦点的时候直接选中无用的部分。

我们就需要用到下面的主角:HTMLInputElement.setSelectionRange(),支持我们设置开始位置和结束位置,来实现input的选中效果。

HTMLInputElement.setSelectionRange(selectionStart, selectionEnd, [optional] selectionDirection)

selectionStart:0开始索引的字符开始选定的字符位置;
selectionEnd:0开始索引的字符最后选定的字符后的位置(测试所得:在chrome39版本等旧的浏览器上面,selectionEnd必须是正数,在新版本的chrome62版本上面,selectionEnd可以为负数,表示从字符的最后一位开始算起,比如-1表示最后一位,-2表示倒数第二位);
selectionDirection[可选参数]:forward” or “backward”, or “none”(但是我测试好想不起作用)

下面给一个例子,可以直接点击此处进行查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>input select</title>
<script>
function inputSelect () {
var input = document.getElementById("textbox");
input.focus();
// 下面四种写法效果是一样的,所以设置的selectionDirection好像不起作用
input.setSelectionRange(0, 3);
// input.setSelectionRange(0, -1); //全选的实现方式;chrome62版本新浏览器
// input.setSelectionRange(0, input.value.length); //全选的实现方式;chrome39版本旧浏览器
// input.setSelectionRange(0, 3, "backword");
// input.setSelectionRange(0, 3, "forword");
// input.setSelectionRange(0, 3, "none");
}
</script>
</head>
<body>
<p><input type="text" id="textbox" value="abcdefg"/></p>
<p><button onclick="inputSelect()">Select text</button></p>
</body>
</html>

所以说在使用HTMLInputElement.setSelectionRange()的时候,最好的切兼容低版本的方式是不采用负数形式,就好比如全选,初始位置0,终止位置为value的length。

IE11版本好像才兼容input type=”number”,但是现在Win7版本操作系统下,很多人的IE版本都是IE7/8/9,所以为了体验就自己写了一个小插件,支持设置最大值、最小值、数字间隔。大家可以试着用一下,如果有哪些Bug欢迎指出,后期修改。

用法说明

  1. 首先必须引入jQuery(由于我是用的是1.11.3版本,如果其他版本有问题欢迎指出、后期修改)
  2. 在所有代码最后引入inputNumber.css和inputNumber.js文件,如:
1
2
3
4
<!--[if IE]>
<link rel="stylesheet" href="css/inputNumber.css">
<script src="js/inputNumber.js"></script>
<![endif]-->

3、支持设置最大值、最小值、数字间隔
4、引用的时候请注意路径问题
下面是一个例子(此处仅贴出html代码,至于css、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
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Firefox和IE对input number的兼容</title>
<script src="js/jquery-1.11.3.js"></script>
<style>
* {margin: 0;padding: 0;}
.input-style{width: 150px;height: 20px;}
</style>
</head>
<body>
<div class="inputNumber-relative">
<input class="input-style" type="number" name="number" id="inputNumber" min="5" max="55" step="3">
</div>
<!--[if IE]>
<link rel="stylesheet" href="css/inputNumber.css">
<script src="js/inputNumber.js"></script>
<![endif]-->
<script>
/**
* IE低版本和Firefox对input type="number"的兼容(因为Firefox中input type="number"依然可以输入非数字内容)
* 可按的按键包括数字(键盘上字母上的数字和小键盘中的数字)、删除键、Tab切换键、减号按键、小数点键
*/
$("#inputNumber").on("keydown", function (event) {
var event = event.which ? event.which : window.event.keyCode;
if (event == 8 || event == 9 || event == 109 || event == 110 || (event >= 48 && event <= 57) || (event >= 96 && event <= 105)) {
return true;
} else {
return false;
}
});
</script>
</body>
</html>

实现的效果如下(在IE9下面上下键的点击、滚轮滚动增减值都支持,在IE7/8下面仅支持上下点击事件):
效果图
所有文件的下载地址:http://download.csdn.net/download/fxss5201/9757758

今天观看学习Element的源码,看到textarea有一个自适应高度的属性,毕竟以前也接触过这方面的问题,你可以查看此处:更强大的textarea高度自适应来了解我之前写的一篇同样是实现textarea自适应高度,所以就好奇看一下它是怎么实现的。

先来看一下它的源码吧(各个阶段大致的做的事情我已经标到代码上了):

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
let hiddenTextarea;

const HIDDEN_STYLE = `
height:0 !important;
visibility:hidden !important;
overflow:hidden !important;
position:absolute !important;
z-index:-1000 !important;
top:0 !important;
right:0 !important
`;

// 所有可能会影响到height的css属性
const CONTEXT_STYLE = [
'letter-spacing',
'line-height',
'padding-top',
'padding-bottom',
'font-family',
'font-weight',
'font-size',
'text-rendering',
'text-transform',
'width',
'text-indent',
'padding-left',
'padding-right',
'border-width',
'box-sizing'
];

// 获取设置在当前textarea上的css属性
function calculateNodeStyling(targetElement) {
const style = window.getComputedStyle(targetElement);

const boxSizing = style.getPropertyValue('box-sizing');

const paddingSize = (
parseFloat(style.getPropertyValue('padding-bottom')) +
parseFloat(style.getPropertyValue('padding-top'))
);

const borderSize = (
parseFloat(style.getPropertyValue('border-bottom-width')) +
parseFloat(style.getPropertyValue('border-top-width'))
);

const contextStyle = CONTEXT_STYLE
.map(name => `${name}:${style.getPropertyValue(name)}`)
.join(';');

return { contextStyle, paddingSize, borderSize, boxSizing };
}

export default function calcTextareaHeight(
targetElement,
minRows = 1,
maxRows = null
) {
// 如果不存在就新建一个隐藏的textarea
if (!hiddenTextarea) {
hiddenTextarea = document.createElement('textarea');
document.body.appendChild(hiddenTextarea);
}

let {
paddingSize,
borderSize,
boxSizing,
contextStyle
} = calculateNodeStyling(targetElement);

// 将获取到得当前得textarea的css属性作用于隐藏的textarea
hiddenTextarea.setAttribute('style', `${contextStyle};${HIDDEN_STYLE}`);
// 将当前的textarea的value设置到隐藏的textarea上面
hiddenTextarea.value = targetElement.value || targetElement.placeholder || '';

// 获取隐藏的textarea的height
let height = hiddenTextarea.scrollHeight;
const result = {};

if (boxSizing === 'border-box') {
height = height + borderSize;
} else if (boxSizing === 'content-box') {
height = height - paddingSize;
}

hiddenTextarea.value = '';
let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;

// 如果设置有最小行数和最大行数时的判断条件
if (minRows !== null) {
let minHeight = singleRowHeight * minRows;
if (boxSizing === 'border-box') {
minHeight = minHeight + paddingSize + borderSize;
}
height = Math.max(minHeight, height);
result.minHeight = `${ minHeight }px`;
}
if (maxRows !== null) {
let maxHeight = singleRowHeight * maxRows;
if (boxSizing === 'border-box') {
maxHeight = maxHeight + paddingSize + borderSize;
}
height = Math.min(maxHeight, height);
}
// 将得到的height的高度设置到当前的textarea上面
result.height = `${ height }px`;
// 删除掉无用的隐藏的textarea
hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea);
hiddenTextarea = null;
return result;
};

大致思路就是将当前textarea的所有可能会影响到height的css属性全部设置给一个隐藏的textarea上,并且两个的value一样,再将隐藏的textarea的高度设置给当前的textarea,如果设置有最小和最大行数,则再做相应的事件。

如果您不太清楚getComputedStyle和getPropertyValue,可以直接查看此处http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/

不过这个是Element的一个文件,我们一般情况下也没办法使用,所以我就想办法把它修改为了一个依赖与jQuery的js文件,使用的时候只需要直接引用这个js文件就可以了,其他事件都不需要做,并且也支持设置最小和最大行数的。

下面放上一个例子:
html:

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
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>textarea自适应高度</title>
<style>
textarea {
display: block;
resize: vertical;
padding: 5px 15px;
line-height: 1.5;
box-sizing: border-box;
width: 100%;
font-size: 14px;
color: #5a5e66;
background-color: #fff;
background-image: none;
border: 1px solid #d8dce5;
border-radius: 4px;
transition: border-color .2s cubic-bezier(.645,.045,.355,1);
margin-bottom: 20px;
}
</style>
</head>
<body>
<textarea name="text" cols="30" rows="1"></textarea>
<textarea name="text" cols="30" rows="2"></textarea>
<textarea name="text" cols="30" data-min-rows="2" data-max-rows="4"></textarea>
<script src="http://apps.bdimg.com/libs/jquery/1.11.3/jquery.js"></script>
<script src="autoheight-textarea.js"></script>
</body>
</html>

autoheight-textarea.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
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
$(function() {
var hiddenTextarea;

var HIDDEN_STYLE = `
height:0 !important;
visibility:hidden !important;
overflow:hidden !important;
position:absolute !important;
z-index:-1000 !important;
top:0 !important;
right:0 !important;
`;

// 所有可能会影响到height的css属性
var CONTEXT_STYLE = [
'letter-spacing',
'line-height',
'padding-top',
'padding-bottom',
'font-family',
'font-weight',
'font-size',
'text-rendering',
'text-transform',
'width',
'text-indent',
'padding-left',
'padding-right',
'border-width',
'box-sizing'
];
// 获取设置在当前textarea上的css属性
function calculateNodeStyling(targetElement) {
var style = window.getComputedStyle(targetElement);

var boxSizing = style.getPropertyValue('box-sizing');

var paddingSize = (
parseFloat(style.getPropertyValue('padding-bottom')) +
parseFloat(style.getPropertyValue('padding-top'))
);

var borderSize = (
parseFloat(style.getPropertyValue('border-bottom-width')) +
parseFloat(style.getPropertyValue('border-top-width'))
);

var contextStyle = CONTEXT_STYLE
.map(function(value){
return value + ':' + style.getPropertyValue(value)
}).join(';');

return { contextStyle, paddingSize, borderSize, boxSizing };
}
$('body').on('focus', 'textarea', function () {
// 如果不存在就新建一个隐藏的textarea
var _this = $(this);
if (!hiddenTextarea) {
hiddenTextarea = document.createElement('textarea');
document.body.appendChild(hiddenTextarea);
}
var {
paddingSize,
borderSize,
boxSizing,
contextStyle
} = calculateNodeStyling(_this[0]);
// 将获取到得当前得textarea的css属性作用于隐藏的textarea
hiddenTextarea.setAttribute('style', HIDDEN_STYLE + contextStyle);
}).on('keydown keyup', 'textarea', function(){
var _this = $(this);
var {
paddingSize,
borderSize,
boxSizing,
contextStyle
} = calculateNodeStyling(_this[0]);
// 将获取到得当前得textarea的css属性作用于隐藏的textarea
hiddenTextarea.setAttribute('style', HIDDEN_STYLE + contextStyle);
// 将当前的textarea的value设置到隐藏的textarea上面
hiddenTextarea.value = _this[0].value || _this[0].placeholder || '';

// 获取隐藏的textarea的height
var height = hiddenTextarea.scrollHeight;

if (boxSizing === 'border-box') {
height = height + borderSize;
} else if (boxSizing === 'content-box') {
height = height - paddingSize;
}

hiddenTextarea.value = '';
var singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;

// 如果设置有最小行数和最大行数时的判断条件,如果没有设置则取rows为最小行数
var minRows = _this.attr('rows') ? _this.attr('rows') : _this.attr('data-min-rows') ? _this.attr('data-min-rows') : 1;
var maxRows = _this.attr('data-max-rows') ? _this.attr('data-max-rows') : null;
if (minRows !== null) {
var minHeight = singleRowHeight * minRows;
if (boxSizing === 'border-box') {
minHeight = minHeight + paddingSize + borderSize;
}
height = Math.max(minHeight, height);
}
if (maxRows !== null) {
var maxHeight = singleRowHeight * maxRows;
if (boxSizing === 'border-box') {
maxHeight = maxHeight + paddingSize + borderSize;
}
height = Math.min(maxHeight, height);
}

// 将得到的height的高度设置到当前的textarea上面
_this.css('height', height + 'px');
}).on('blur', 'textarea', function () {
// 删除掉无用的隐藏的textarea
hiddenTextarea.parentNode && hiddenTextarea.parentNode.removeChild(hiddenTextarea);
hiddenTextarea = null;
})
})

Element的源码还是写的很赞的,有时间多看看各种框架的源码。

你能看到这篇文章,相信你一位程序员吧。
作为一名程序员,我们每天的工作是干什么呢?

我们每天都在不断的破而后立,所以说我们很累的。

每个新项目开始,我们最怕的就是:

对,就是项目组长来提需求。

开发结束之后,你以为就完了吗,不,它是另一个的开始:

然后我们只能:

最后为了按时发布只能加班成这样:

在程序员的发展道路是:

所以有一个好的身体很重要,在久坐/加班/饮食不规律的情况下,不知道你有没有发现你现在吃饭的时候经常是食之无味,不吃又饿的状态,这是因为你消化不良,这个时候你就需要来点水果助消化了。

下面介绍一款可以陪伴你大半年的一种水果:苹果,先来爆个照,大家看看怎么样


怎么样,光看照片是不是都有一种食欲大开的感觉。
什么,你关心它的生长环境:


在苹果很小的时候,我们就为每个苹果穿上一件薄膜(TT),很安全的呦,防止蚊虫叮咬,防止药物残留,留给它安全的生长环境。

什么,你还担心它的采摘过程:

在农田里全部手工采摘,放在定制的塑料框内,防止磕碰。

什么,你还担心运输:


我们有专用的快递箱/花格/网套,给每个苹果都有一个愉快的旅程送达您的手中。

如果你想来一箱的话,可以直接联系我:
樊先生:QQ:723107234 /1966443979
微信:

最近学习了一段时间Vue,把文档看完之后有点懵懵懂懂,不过刚好赶上Element和iView等应用Vue编写的框架,就先看完文档,然后看了Element的源码,来巩固自己对Vue的见知。

在阅读本系列文章之前,希望你可以做到:

  1. 系统阅读一遍Vue文档;
  2. 系统查看一下Element的官方文档(本系列文章以Element 2.0.3版本做说明)

首先先说一下,直接从github上面得到的源码是无法编译的,我们可以用如下方法来运行:

在Element官方文档的快速上手里面,有为我们提供的项目模板,也就是下面的这个链接:https://github.com/ElementUI/element-starter

直接将其拷贝到本地,在你已经成功安装node.js和npm的情况下,直接:

1
npm install

或者是使用淘宝镜像直接:

1
cnpm install

推荐使用淘宝镜像,毕竟快。依赖安装完成之后,我们可以直接:

1
npm run dev

这个时候基本上就可以得到如下的目录结构:
目录结构
之后就可以直接将Element官方文档中的示例代码复制在App.vue文件中,进行查看。例如下面这样:

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<template>
<el-container>
<el-header>
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<div class="fl title">管理后台</div>
<div class="fr">
<el-menu-item index="1">处理中心</el-menu-item>
<el-submenu index="2">
<template slot="title">我的工作台</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
<el-menu-item index="2-3">选项3</el-menu-item>
</el-submenu>
<el-menu-item index="3"><a href="https://www.ele.me" target="_blank">订单管理</a></el-menu-item>
</div>
</el-menu>
</el-header>
<el-main>
<el-container>
<el-aside width="240px">
<el-row class="tac">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>导航一</span>
</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项1</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</el-menu-item>
<el-menu-item index="3">
<i class="el-icon-setting"></i>
<span slot="title">导航三</span>
</el-menu-item>
</el-menu>
</el-row>
</el-aside>
<el-container>
<el-main>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</el-main>
<el-footer>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage"
:page-size="100"
layout="total, prev, pager, next"
:total="1000">
</el-pagination>
</el-footer>
</el-container>
</el-container>
</el-main>
</el-container>
</template>

<script>
export default {
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
activeIndex: '2-1',
tableData: Array(5).fill(item),
currentPage: 5,
};
},
methods: {
handleSelect(key, keyPath) {
console.log(key, keyPath);
},
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
}
}
}
</script>

<style>
.fl {
float: left;
}
.fr {
float: right;
}
.title {
width: 125px;
text-align: center;
line-height: 60px;
color: #fff;
}
</style>

就可以直接看到下面的界面:
界面
安装Vue官方提供的devtools有助于我们进行快速开发(只不过chrome商店由于访问等原因可能下载不到,不过我们可以使用Firefox的插件),而且还可以直接浏览器中查看插件直接数据/计算属性/方法等的计算结果,对插件内部的情况一目了然,如下图所示:
devtools

做好这些准备之后,下章我们来正式从Element融会贯通Vue的使用方法。