工作记录
哈哈,码农一个,记录一下使用率较高又经常忘记的东西。省的要用的时候到处找代码复制粘贴
async-validator 表单校验
一个表单校验库,Antd 和 ElenentUI 表单组件使用的就是这个库,对输入框比较多的表单使用很方便,避免了无尽的
if ... return。 英文不好还可以看别人翻译的文档
具体用法就不多说了,直接看文档。码农都是直接上代码的,哈哈哈
<script>
import Schema from 'async-validator'
export default {
name: 'ReplyWorkPage',
data () {
return {
form: { // form是表单校验的数据源
solutions: '', // 处理方案
resolved_quickly: '1', // 是否当天处理 1是 0不是
estimated_time: '1', // 预估处理时效/天
remark: '',
change_responsible: '1',
},
errorText: {
solutions: '',
resolved_quickly: '',
estimated_time: '',
},
// rules 是表单校验规则。有多种校验方式,这里只是展示了两种,具体看文档
rules: {
solutions: {
type: 'string',
required: true,
message: '请输入处理方案',
},
resolved_quickly: {
type: 'string',
required: true,
message: '选择是否当天解决',
},
estimated_time: {
type: 'string',
message: '请输入预估时效',
validator: (rule, value) => {
// 比较复杂或者有依赖的校验,可以自定义校验方法,return false则不通过
if (this.form.resolved_quickly === '0' && !value) {
return false
}
return true
},
},
},
validator: null,
}
},
methods: {
changeValue (field, value) {
this.$set(this.form, field, value)
// 校验单个输入框
this.validateSingleField(field)
},
onError ({ ret, errmsg }) {
this.$toast.center(errmsg)
},
onSubmit () {
// 校验前需要new Schema实例
this.validator = new Schema(this.rules)
this.validator.validate(this.form).then(() => {
// 全部一起校验
console.log('校验成功!')
for (let key in this.errorText) {
this.errorText[key] = ''
}
// TODO:校验完成需要的操作
}).catch(({ errors, fields }) => {
// 校验错误的话,fields会包含所有检验失败的数据,打log就一目了然了
for (let field in this.rules) {
if (fields[field] && fields[field].length) {
this.errorText[field] = fields[field][0].message
} else {
this.errorText[field] = ''
}
}
})
},
validateSingleField (field) {
// 单个表单的校验,需要将rules的单个挑出来
if (!this.rules[field]) { return }
const validator = new Schema({
[field]: this.rules[field],
})
validator.validate(this.form).then(() => {
this.errorText[field] = ''
}).catch(({ errors, fields }) => {
this.errorText[field] = errors[0].message
})
},
remarkFocus () {
if (browser.versions.android) {
let that = this
setTimeout(function () {
that.$refs.remarkArea.scrollIntoView(false)
}, 300)
}
},
},
}
</script>
async-validator 还有很多其他的校验功能,可以完成非常复杂的校验,我这个只是最基本的用法,惭愧呀。
软键盘触发搜索
像原生app那样,页面搜索框旁边不需要搜索按钮,可以通过软键盘右下角的搜索按钮直接出发H5的表单搜索。这种体验更好。
主要是要处理4个问题:
- 表单需要包在
form标签中 <input type="search" />type为search才能是让软键盘出现 “搜索” 按钮- 监听
input的search事件 - 修改搜索框后面默认的取消文字输入的小图标
TODO: 缺一张图
码农直接上代码:
<template>
<section>
<!-- onsubmit="return false" 阻止表单默认的行为 -->
<form action="#" onsubmit="return false" class="search-input-form">
<input
ref="productNameInput"
v-model="filter.title"
type="search"
class="search-input"
@search="productSearch"
placeholder=" 请输入关键词" />
</form>
</section>
</template>
<style lang="scss">
.search-input {
width: 100%;
height: 40px;
line-height: 40px;
border: none;
outline: none;
font-size: 28px;
text-align: left;
color: #333;
background-color: transparent;
&::placeholder { /* 大部分现代浏览器 */
color: #B3B3B3;
}
/* 修改默认的清除图标样式 */
&::-webkit-search-cancel-button {
-webkit-appearance: none;
position: relative;
width: 32px;
height: 32px;
background: url("./imgs/icon-close.png") no-repeat center;
background-size: 32px 32px;
}
/* ios15以上,在type=search时会在前面显示一个默认的搜索图标,这是我们不期望的,可以隐藏 */
&::-webkit-search-decoration {
display: none;
}
}
</style>
下拉加载更多
移动端常见的下拉加载更多,也可以直接使用
better-scroll 1.x实现。
实现方法很简单:
- 外层一个固定高度的容器,设置超出滚动
- 内层一个容器,高度随内容的高度
- 监听外层容器的滚动事件
- 判断距离底部多远,触发加载
码农直接上代码:
<template>
<!-- 外层容器,固定高度的 -->
<div class="timeline-block" id="timeline-scroll">
<!-- 内层容器 -->
<div>
<!-- 无尽的内容 -->
<div
v-for="item in materialLists"
:key="item.id"
class="row timeline-li"
></div>
</div>
</div>
</template>
<script>
import { throttle } from 'lodash'
let scrollFn = null
export default {
data () {
return {
scrollDom: null, // 滚动的容器
scrollDomFirstChild: null, // 滚动容器中的第一个元素
scrollDomHeight: 0, // 滚动容器的高度
}
},
mounted () {
if (!this.filter.id) {
this.initBscroll()
}
},
methods: {
initBscroll () {
this.scrollDom = document.querySelector('#timeline-scroll')
this.scrollDomFirstChild = this.scrollDom.children[0]
if (this.scrollDomFirstChild) {
this.scrollDomHeight = this.scrollDom.offsetHeight || 800
// 节流
scrollFn = throttle(this.beforeGetNews, 300)
// 监听滚动
this.scrollDom.addEventListener('scroll', scrollFn)
}
},
beforeGetNews () {
// 当滚动到距离底部一屏距离的时候就开始加载下一页
// 内层容器的高度(即内容的总高度)- (外层容器的滚动高度+外层容器的高度) 的差值 小于 外层容器的高度时
// 说明距离底部小于一个外层容器的高度了
// this.scrollDomFirstChild.offsetHeight - (this.scrollDom.scrollTop + this.scrollDomHeight) <= this.scrollDomHeight
if (this.scrollDomFirstChild.offsetHeight <= this.scrollDomHeight * 2 + this.scrollDom.scrollTop && !this.isNoMoreData) {
this.getDate()
}
},
getDate () {
if (this.isRequestLock) {
return
}
this.isRequestLock = true
getFriendMaterialList({
...this.filter,
}).then(res => {
let lists = res.data || []
if (this.filter.page === 1) {
this.materialLists = lists
if (lists.length) {
this.isEmptyData = false
} else {
this.isEmptyData = true
}
} else {
this.materialLists = this.materialLists.concat(lists)
}
this.filter.page++
if (lists.length === 0) {
this.materialLists = []
this.$toast.center('当前筛选没有更多数据了~')
}
if (lists.length < this.filter.size) {
this.isNoMoreData = true
}
this.isRequestLock = false
}).catch(err => {
console.error('getFriendMaterialList', err)
this.isRequestLock = false
this.$toast.center(err.message || err || '获素材列表失败')
})
},
removeBscroll () {
this.scrollDom && this.scrollDom.removeEventListener('scroll', scrollFn)
},
},
destroyed () {
this.removeBscroll()
scrollFn = null
},
}
</script>
input placeholder样式修改
这个老是忘记,码农记性就是不好
&::-webkit-input-placeholder { /* WebKit, Blink, Edge */
font-size: 28px;
color: #B3B3B3;
}
&:-moz-placeholder { /* Mozilla Firefox 4 ~ 18 */
font-size: 28px;
color: #B3B3B3;
opacity: 1;
}
&::-moz-placeholder { /* Mozilla Firefox 19+ */
font-size: 28px;
color: #B3B3B3;
opacity: 1;
}
&:-ms-input-placeholder { /* Internet Explorer 10 ~ 11 */
font-size: 28px;
color: #B3B3B3;
}
&::-ms-input-placeholder { /* Microsoft Edge */
font-size: 28px;
color: #B3B3B3;
}
&::placeholder { /* 大部分现代浏览器 */
font-size: 28px;
color: #B3B3B3;
}
超过省略…
.duohang {
/* 多行 */
display: -webkit-box;
/* autoprefixer: ignore next */
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.single-line {
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
-webkit-line-clamp 用来限制在一个块元素显示的文本的行数。 为了实现该效果,它需要组合其他的WebKit属性。
display: -webkit-box; 必须结合的属性 ,将对象作为弹性伸缩盒子模型显示 。
-webkit-box-orient 必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式 。
/* autoprefixer: ignore next */ 这个注释是因为低版本会去除 -webkit-box-orient: vertical; 这行代码,9.6.1版本修复了
参考: