共计 4752 个字符,预计需要花费 12 分钟才能阅读完成。
总文件入口 -index.vue
用户使用层
- 主要是用来定义:
- 校验规则
- 登陆事件处理(全部校验通过与否调用全局弹窗)
项目结构说明
用户入口文件 -inex.vue
<template> | |
<div> | |
<Vfrom :model="model" :rules="rules" ref="from"> | |
<Vfromitem label="用户名" prop="username"> | |
<Vinpnt v-model="model.username"></Vinpnt> | |
</Vfromitem> | |
<Vfromitem label="密码" prop="password"> | |
<Vinpnt v-model="model.password"></Vinpnt> | |
</Vfromitem> | |
<Vfromitem> | |
<button @click="login"> | |
提交 | |
</button> | |
</Vfromitem> | |
</Vfrom> | |
{{model}} | |
</div> | |
</template> | |
<script> | |
import Vfrom from './vfrom'; | |
import Vfromitem from './vfromitem'; | |
import Vinpnt from './vinput'; | |
export default { | |
components:{ | |
Vfrom, | |
Vfromitem, | |
Vinpnt | |
}, | |
data() { | |
return { | |
model:{ | |
username: 'sss', | |
password:'' | |
}, | |
rules:{ | |
username:[{required:true, message:'请输入姓名'}, | |
], | |
password:[{required:true, message:'请输入密码'}, | |
] | |
} | |
} | |
}, | |
methods:{login(){this.$refs.from.validator((isvalid)=>{// console.log(isvalid, 'isvalid') | |
// if(isvalid) {// console.log('验证通过') | |
// } else {// console.log('验证失败') | |
// } | |
// this.$notice({ | |
// title:'校验结果', | |
// message:isvalid?'验证通过':'验证失败', | |
// duration:2000 | |
// }).show() | |
// console.log(isvalid,'isvalid') | |
this.$notice({ | |
title: '校验结果', | |
message: isvalid ? '请求登录' : '校验失败', | |
duration: 2000 | |
}).show()}) | |
} | |
} | |
} | |
</script> | |
<style> | |
</style> |
提交按钮
<button @click="login"> 登录 </button>
登陆事件处理(全部校验通过与否调用全局弹窗)
全局校验 -From.vue
- 全局的校验,调用每个自组建的校验结果
<template> | |
<div> | |
<slot></slot> | |
</div> | |
</template> | |
<script> | |
export default { | |
name:'vfrom', | |
provide(){ | |
return{from: this} | |
}, | |
props:{ | |
model:{ | |
type:Object, | |
requiree:true | |
}, | |
rules:Object | |
}, | |
methods:{validator:function(cb){ | |
const tasks =this.$children | |
.filter(item=> item.prop) | |
.map(item=> item.validator()) | |
Promise.all(tasks) | |
.then(()=>{cb(true)}) | |
.catch(()=>{cb(false)}) | |
} | |
} | |
} | |
</script> | |
<style> | |
</style> |
单一 input 内容校验 -FromItem.vue
- 获取校验规则
- 获取当前的值
- import Schema from “async-validator”; 引入校验模块
- 创建校验规则
- 执行校验
- if(erro){thi.message=’ 错误信息 ’}else{this.messgae=”}
<template> | |
<div> | |
<label :for="prop">{{label}}</label> | |
<slot></slot> | |
<span v-if="error">{{error}}</span> | |
</div> | |
</template> | |
<script> | |
import Schema from 'async-validator'; | |
export default { | |
name: 'vfromitem', | |
inject:['from'], | |
props:{ | |
// label="用户名" prop="username" | |
label:{ | |
default:'', | |
type:String | |
}, | |
prop:{ | |
default:'', | |
type:String | |
} | |
}, | |
data() { | |
return {error:''} | |
}, | |
mounted(){this.$on('validator', ()=>{this.validator() | |
}) | |
}, | |
methods:{validator:function(){// console.log('进来了吗') | |
// 获取校验规则 | |
const rules =this.from.rules[this.prop] | |
// 获取当前的值 | |
const value =this.from.model[this.prop] | |
// 创造校验器 | |
const schema= new Schema({[this.prop]:rules | |
}) | |
// console.log({[this.prop]:rules}, '[this.prop]:rules') | |
return schema.validate({[this.prop]:value | |
},errors=>{// console.log(errors,'sdsds') | |
if(errors){this.error=errors[0].message | |
}else{this.error=''} | |
}) | |
} | |
} | |
} | |
</script> | |
<style> | |
span{ | |
color:red; | |
font-size: 10px; | |
} | |
</style> |
type:text 填写信息 -Input.vue
- 改变 value 值
- 调用父组建校验方法
<template> | |
<div> | |
<input :type="type" :value="value" @input="Oninput"> | |
</div> | |
</template> | |
<script> | |
export default { | |
name:'vinput', | |
props:{ | |
type:{ | |
type:String, | |
default:'text' | |
}, | |
value:{ | |
type:String, | |
default:'' | |
} | |
}, | |
methods:{Oninput:function (e) {this.$emit('input',e.target.value) | |
this.$parent.$emit('validator') | |
} | |
} | |
} | |
</script> | |
<style> | |
</style> |
通知全局组建 -Vue.prototype.$notice
(弹窗类组建封装)- 全局注册组建
- 在 vue 定义方法 $notice
- 方法内部调用 create 方法
- 传入组建和 props
使用 new Vue 生成组建挂在在 dome 上;
思路:
- 创建 dom 元素
- 将 dom 元素放在 body 里面
- 显示后,消失操作,删除 dom 元素以及销毁实例
在 new Vue 中,redner 中的参数 h
h:是一个 `createElement 函数 ` 可以返回一个虚拟 dome
调用
new Vue().$mount()
`$mount()` 的目的:将 vdome -> dom
vm
`vm` : new Vue()构造函数
vm.$el
真实的 dom 元素
vm.$children
[Vuecomponent]
const comp = vm.$children[0] comp.remove=()=>{}
给 vue 组建定义删除组建的方法 | |
使用 new Vue 生成组建挂在在 dome 上; |
/utils/create- 构造组件实例
import Vue from 'vue' | |
// 实现一个 create 方法,能够创建指定组件实例 | |
// 并将其挂载至 body 上 | |
// Component 是组件配置对象 | |
export default function create(Component, props) { | |
// 怎么创建组件实例 | |
// 方案 1:可以通过 Vue.extend(Component)获取组件构造函数 | |
// const Ctor = Vue.extend(Component) | |
// const comp = new Ctor() | |
// 方案 2:借助 Vue 构造组件实例 | |
const vm = new Vue({render(h) { | |
// h 是 createElement 函数,可以返回 vdom | |
return h(Component, {props}) | |
} | |
}).$mount() // $mount()目标:将 vdom=》dom | |
// 手动追加 dom | |
document.body.appendChild(vm.$el) | |
const comp = vm.$children[0] | |
// 淘汰逻辑 | |
comp.remove = () => {document.body.removeChild(vm.$el) | |
// 执行 remove 方法时,执行 $destroy 销毁实例 | |
comp.$destroy()} | |
return comp | |
} |
组建内容 -/components/Notice.vue
<template> | |
<div class="box" v-if="isShow"> //ishow 是用来判断是否展示 | |
<h3>{{title}}</h3> // 传入进来的参数的 title | |
<p class="box-content">{{message}}</p> // 提示信息 | |
</div> | |
</template> |
<script> | |
export default { | |
props: { | |
title: { // 弹窗的标题 | |
type: String, | |
default: "" | |
}, | |
message: { // 展示内容 | |
type: String, | |
default: "" | |
}, | |
duration: { // 延迟的关闭的时间 | |
type: Number, | |
default: 1000 | |
} | |
}, | |
data() { | |
return {isShow: false // 默认组建为隐藏状态不限时}; | |
}, | |
methods: {show() { | |
// 调用 show 方法显示组建时,先将内部 data 定义的 isShow 改为 true | |
// 展示之后,执行 hide 进行隐藏。使用 setTimeout;隐藏的时间将有传进来的参数进行调动 | |
this.isShow = true; | |
// 当执行 show 方法之后,执行 hide 方法 | |
setTimeout(this.hide, this.duration); | |
}, | |
hide() { | |
this.isShow = false; | |
this.remove();} | |
} | |
}; | |
</script> |
<style> | |
.box { | |
position: fixed; | |
width: 100%; | |
top: 16px; | |
left: 0; | |
text-align: center; | |
pointer-events: none; | |
background-color: #fff; | |
border: grey 3px solid; | |
box-sizing: border-box; | |
} | |
.box-content { | |
width: 200px; | |
margin: 10px auto; | |
font-size: 14px; | |
padding: 8px 16px; | |
background: #fff; | |
border-radius: 3px; | |
margin-bottom: 8px; | |
} | |
</style> |
学习资源
思维导图:https://www.processon.com/vie…
github:https://github.com/speak44/Vu…
正文完
发表至: javascript
2020-06-22