Vue.js 进阶技巧Day01: 获取DOM节点,获取子组件对象,跨组件通信/依赖注入,表单验证实例

7 篇文章 0 订阅

目录

0x00 $refs、$parent 、$children

0x02 provide 和 inject 跨多组件通信 依赖注入

0x03 表单验证实例


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>

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值