目录
0x02 provide 和 inject 跨多组件通信 依赖注入
0x00 $refs、$parent 、$children
获取普通元素的dom节点,只需要给要获取的dom节点一个ref属性 作为标志
<!-- 获取普通元素 -->
<input type="text" class='form-control' ref="iamshangrui">
然后通过this.$refs.标志名 皆可以获取到 对应的dom对象,之后的dom操作 和原生的dom操作相同
注意必须在页面渲染完成之后,才能获取到dom节点
export default{
//页面渲染完成的时候
mounted(){
//获取input的dom节点
// console.log(this.$refs.iamshangrui)
//修改样式 : 和以前的dom操作一样
this.$refs.iamshangrui.style.borderColor ='red'
//获取焦点
this.$refs.iamshangrui.focus()
}
}
如果多个元素的ref属性值相同,那么通过this.$refs.标志名 获取到的将是一个数组
<!-- 获取列表 -->
<ul class='list-group'>
<li class='list-group-item' v-for='(item,index) in list' :key='index' ref='list'>item{{item}}</li>
</ul>
console.log(this.$refs.list);
this.$refs.list[3].style.background ='#ccc';
获取子组件 并调用子组件中的方法
<template>
<div>
<h2>This is Input</h2>
<input type="text" v-model='val' class='form-control' ref='input'>
</div>
</template>
<script>
export default {
data(){
return {
val:'输入框'
}
},
methods:{
focus(){
console.log("this is focus")
this.$refs.input.focus()
}
}
}
</script>
<!-- 获取组件 -->
<demo-item ref='demoItem'></demo-item>
同样需要给子组件一个ref标志
//获取子组件
console.log(this.$refs.demoItem)
//调用子组件中的focus方法
this.$refs.demoItem.focus()
通过父组件调用子组件中的方法,可以用来修改子组件中的数据
export default {
data(){
return {
header:"标题",
val:'输入框'
}
},
methods:{
focus(){
console.log("this is focus")
this.$refs.input.focus()
},
renameHeader(data){
this.header = data;
}
}
}
this.$refs.demoItem.renameHeader("Hello world")
也可以直接 修改子组件中的数据
this.$refs.demoItem.header="123456"
还有更加简便的方式:不需要加ref,直接用$children 来获取
this.$children; //获取该组件/页面的所有 子组件对象 组成的数组
this.$children[0].header ='hello world'
子组件中获取父组件,并修改父组件中的数据
this.$parent 获取到该子组件的父组件
this.$parent.数据名 = 值
this.$parent.title="秋天的奶茶"
this.$parent.方法名 调用父组件的方法
0x02 provide 和 inject 跨多组件通信 依赖注入
父组件可以通过provide 将 数据 和方法 暴露出来,
子组件(或 孙子组件)通过inject 来 接收调用
export default {
provide(){
return {
title:this.title,
rename:this.rename
}
},
data(){
return {
title:"父组件标题"
}
},
components:{
demoItem
},
methods:{
rename(data){
this.title = data
}
}
}
子组件:
<script>
export default{
inject:['title','rename'],
methods:{
clickEvent(){
this.rename("哈哈哈")
}
}
}
</script>
0x03 表单验证实例
demo.vue
<template>
<div class='container p-5'>
<!-- <form>
<div class="form-group">
<label for="username">用户名</label>
<input type='text' class="form-control is-valid" id="username">
<div class="valid-feedback">
验证通过
</div>
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" class="form-control is-invalid" id="email">
<div class="invalid-feedback">
邮箱不能为空
</div>
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form> -->
<z-form :form='form' :validate='validate'>
<z-form-item label='用户名' name='username'>
<input type='text' class="form-control" id="username" v-model='form.username'>
<!-- 当form.username 变化时,z-form就会监听到form的变化,然后通知给子组件z-form-item,z-form-item 决定是否显示错误框 -->
</z-form-item>
<z-form-item label="邮箱" name="email">
<input type="text" class="form-control" id="email" v-model='form.email'>
</z-form-item>
<z-form-item>
<button type="submit" class="btn btn-primary">提交</button>
</z-form-item>
</z-form>
</div>
</template>
<script>
import zForm from './z-form.vue'
import zFormItem from './z-form-item.vue'
export default {
components:{
zForm,
zFormItem
},
data() {
return {
//表单数据
form: {
username: "",
email: ""
},
//验证规则
validate: [{
name: "username",
validate: {
required: {
data: true, //true表示必填
msg: "用户名不能为空"
},
rule: {
data:"username",
msg:"用户名格式错误"
}
}
},
{
name: "email",
validate: {
required: {
data: true,
msg: "邮箱不能为空"
},
//自定规则
rule: {
data:'email',
msg:"邮箱格式错误"
}
}
}
]
}
}
}
</script>
<style>
</style>
z-form.vue
<template>
<form>
<slot></slot>
</form>
</template>
<script>
export default{
props:[
'form',
'validate'
],
//注入到子组件
provide(){
return {
form:this.form,
validate:this.validate
}
}
}
</script>
<style>
</style>
z-form-item.vue
<template>
<div class="form-group">
<label :for="name">{{label}}</label>
<slot></slot>
<div :class="status == 1?'valid-feedback':'invalid-feedback'">
{{msg}}
</div>
</div>
</template>
<script>
let rules = {
username: /^[a-zA-Z0-9_-]{4,16}$/,
email: /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/
}
export default{
props:[
'label',
'name'
],
//接收父组件注入的属性
inject:['form','validate'],
data(){
return {
vali:{
},
msg:'验证失败',
status:0, //0 验证未通过 1验证通过
inputDom:''
}
},
methods:{
fail(msg){
this.msg = msg
this.status = 0
//判断当前是否处于失败状态
if(this.inputDom.className.indexOf('is-invalid')>-1){
return;
}
if(this.inputDom.className.indexOf('is-valid')>-1){
return this.inputDom.className = this.inputDom.className.replace(/is-valid/,'is-invalid')
}
this.inputDom.className += ' is-invalid'
},
success(msg){
this.msg = msg
this.status = 1
//判断当前是否处于成功状态
if(this.inputDom.className.indexOf('is-valid')>-1){
return;
}
if(this.inputDom.className.indexOf('is-invalid')>-1){
return this.inputDom.className = this.inputDom.className.replace(/is-invalid/,'is-valid')
}
this.inputDom.className += ' is-valid'
}
},
//页面渲染完成后
mounted(){
//拿到插槽对应的输入框
//如果子组件是slot形式插入的,不能用this.$children拿到子组件,必须用this.$slots
let input = this.$slots.default[0]
if(!input){
return;
}
//真正的dom节点
this.inputDom = input.elm;
console.log(this.inputDom);
//初始化验证规则
this.validate.forEach(item=>{
if(item.name === this.name){
this.vali = item.validate
}
})
//监听字段变化
this.$watch('form.'+this.name,(newValue,oldValue)=>{
//验证数据是否合法
//1.验证是否必填
if(true === this.vali.required.data){
if(newValue.trim() === ''){
console.log('fail')
this.fail(this.vali.required.msg)
return
}
}
//2.验证其他规则
if(this.vali.rule && this.vali.rule.data){
let currentRule = rules[this.vali.rule.data]
if(!currentRule.test(newValue)){
return this.fail(this.vali.rule.msg)
}
}
//3.成功
console.log('success')
this.success("验证通过")
})
}
}
</script>
<style>
</style>