rxjs在特定场景下的妙用
Closed this issue · 0 comments
RaySaii commented
一个简单的vue的表单注册页面,如何结合异步验证。
上代码:
<script>
import {
Observable
} from 'rxjs/Observable'
import fromPromise from 'rxjs/add/observable/fromPromise'
import {
mapMutations
} from 'vuex'
import Tip from './tip.vue'
function checkUsed(name) {
return Observable.fromPromise(new Promise(resolve => {
setTimeout(() => {
if (name === 'signed') {
resolve({
"used": true
});
} else {
resolve({
"used": false
})
}
}, 1000)
}))
};
export default {
name: 'sign',
components: {
Tip
},
data() {
return {
time: '',
name: '',
password: '',
checkPass: '',
pending: false,
errors: {
name: '',
password: '',
checkPass: ''
},
messages: {
name: {
required: '不能为空',
length: '4-18位',
used: '已被使用'
},
password: {
required: '不能为空',
pattern: '8-16位字母与数字组合'
},
checkPass: {
required: '请确认密码',
match: '两次输入不一致'
}
}
}
},
subscriptions() {
this.$watchAsObservable('name')
.pluck('newValue')
.debounceTime(500)
.distinctUntilChanged()
.do(val => {
this.errors.name = '';
let len = val.length;
if (len === 0) {
this.errors.name = this.messages.name.required;
return
};
if (len <= 3 || len >= 19) {
this.errors.name = this.messages.name.length;
return
}
})
.filter(val => val.length > 3 && val.length < 19)
.do(() => this.pending = true)
.switchMap(checkUsed)
.do(() => this.pending = false)
.subscribe(res => {
if (res.used === true) {
this.errors.name = this.messages.name.used
}
})
},
computed: {
vaild() {
for (var field in this.errors) {
if (!this.name || !this.password || !this.checkPass || this.errors[field] !== '') {
return false
}
}
return true
}
},
watch: {
password: function(val) {
this.errors.password = '';
if (val.length === 0) {
this.errors.password = this.messages.password.required;
return
}
var re = new RegExp("^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$");
if (!re.test(val)) {
this.errors.password = this.messages.password.pattern;
}
if (val !== this.checkPass) {
this.errors.checkPass = this.messages.checkPass.match;
}
},
checkPass: function(val) {
this.errors.checkPass = '';
if (val.length === 0) {
this.errors.checkPass = this.messages.checkPass.required;
return
}
if (val !== this.password) {
this.errors.checkPass = this.messages.checkPass.match;
return
}
},
},
created() {
},
mounted() {
},
methods: {
submit() {
console.log(this.name, this.password);
this.$store.commit('sign', {
'name': this.name,
'password': this.password
})
this.time = true;
setTimeout(() => {
this.$router.push('login')
}, 2000)
}
}
}
</script>
这是注册界面的代码。
将name的值变化视作流
间隔超过0.5s视作一次变化
与上一个值不同才发送请求
subscriptions() {
this.$watchAsObservable('name')
.pluck('newValue')
.debounceTime(500)
.distinctUntilChanged()
.do(val => {
this.errors.name = '';
let len = val.length;
if (len === 0) {
this.errors.name = this.messages.name.required;
return
};
if (len <= 3 || len >= 19) {
this.errors.name = this.messages.name.length;
return
}
})
.filter(val => val.length > 3 && val.length < 19)
.do(() => this.pending = true)
.switchMap(checkUsed)
.do(() => this.pending = false)
.subscribe(res => {
if (res.used === true) {
this.errors.name = this.messages.name.used
}
})
},
这是用户输入与验证的部分。利用vue-rx提供的功能,将name变为可观察对象。
filter
是过滤name值的长度。debounceTime
功能是用户抬手0.5秒后看做一次输入distinctUntilChanged
直到值改变再向下传值。do
是做一些流之外的功能的操作符。switchMap
是将符合规则的值,向服务器发送进行验证,可以将请求序列化,比如最近的一次请求如果有返回,那么就不去管其他请求。subscribe
订阅这个可观察对象(指的是请求的返回结果)。这里要注意的是,要将请求的返回结果包装为一个observable
即可观察对象。
function checkUsed(name) {
return Observable.fromPromise(new Promise(resolve => {
setTimeout(() => {
if (name === 'signed') {
resolve({
"used": true
});
} else {
resolve({
"used": false
})
}
}, 1000)
}))
};
vue中网络请求如果要使用rxjs,都要将请求结果变为observable
。