文章目录
- v-model的原理
- 带value属性组件间传值的普通写法
- 解析
- 演示
- 根据v-model的原理 简写带有value属性组件之间的传值
- 解析
- 演示
- 使用sync修饰符,自定义属性名进行组件传值
- 解析
- 案例
v-model的原理
v-model 原理
原理:v-model本质上是一个语法糖
。例如应用在输入框上,就是 value属性
和 input事件
的合写。
作用:提供数据的双向绑定
① 数据变,视图跟着变 :value
② 视图变,数据跟着变 @input
注意:$event
用于在模板中,获取事件的形参
<template><div id="app" ><input v-model="msg" type="text"><input :value="msg" @input="msg = $event.target.value" type="text"></div>
</template>
带value属性组件间传值的普通写法
解析
表单类组件 封装→ 实现 子组件 和 父组件数据 的双向绑定
① 父传子
:数据 应该是父组件 props
传递 过来的,拆解 v-model
绑定数据
② 子传父
:监听输入,子传父传值给父组件修改
演示
<template><div class="app">父组件<!-- 在标签内接收必须使用参数 $event接收 --><Son :selectId="selectId" @change="selectId = $event"></Son><!-- 定义函数接收形参随便写 --><!-- <Son :selectId="selectId" @change="changeSelectId"></Son> --></div>
</template><script>
import Son from "./components/Son.vue";
export default {data() {return {selectId: "2"}},methods: {// 定义函数接收形参随便写changeSelectId(newId) {this.selectId = newId;}},components: {Son},
}
</script><style>
</style>
<template><div>子组件<!-- 这里的button 是自己的点击事件 --><!-- <button @click="$emit('add')">+1</button>{{ count }} --><!-- 这里的select是表单输入事件 对应按钮的点击事件 --><!-- 如果要在页面的下拉菜单展示必须使用value的属性绑定指令 对应{{count}} --><!-- 这里如果在标签内写 必须使用$event --><!-- <select name="" id="" :value="selectId" @input="$emit('change', $event.target.value)"> --><!-- 如果定义函数参数随便定义 @input="事件名" --><select name="" id="" :value="selectId" @input="dian"><option value="1">北京</option><option value="2">上海</option><option value="3">广州</option><option value="4">深圳</option></select></div>
</template><script>
export default {props: ["selectId"],methods: {// 如果定义函数参数随便定义dian(e) {console.log(e.target.value);this.$emit("change", e.target.value);}}
};
</script><style>
</style>
运行结果
根据v-model的原理 简写带有value属性组件之间的传值
解析
父组件 v-model 简化代码
,实现 子组件 和 父组件数据 双向绑定
① 子组件中:props 通过 value 接收,事件触发 input
② 父组件中:v-model 给组件直接绑数据 ( :value + @input )
演示
<template><div class="app">父组件<!-- <Son :selectId="selectId" @change="selectId = $event"></Son> --><!-- v-model的原理是 :value(属性绑定) + @input(表单输入事件) 修改代码如下--><!-- 将父传子的变量改为value, 将自定义的触发事件改为input输入事件--><!-- <Son :value="selectId" @input="selectId = $event"></Son> --><!-- 下面的代码相当于上面的代码, 这样就利用v-model原理简写了 --><Son v-model="selectId"></Son></div>
</template><script>
import Son from "./components/Son.vue";
export default {data() {return {selectId: "2"}},components: {Son},
}
</script><style>
</style>
<template><div>子组件<!-- <select :value="selectId" @input="$emit('change', $event.target.value)"> --><!-- 将父传子的变量改为value, 将自定义的触发事件改为input输入事件 --><select :value="value" @input="$emit('input', $event.target.value)"><option value="1">北京</option><option value="2">上海</option><option value="3">广州</option><option value="4">深圳</option></select></div>
</template><script>
export default {// props: ["selectId"],// 将父传子的变量改为valueprops: ["value"],};
</script><style>
</style>
运行结果
使用sync修饰符,自定义属性名进行组件传值
比如模态框使用value就不太合适。
解析
作用:可以实现 子组件
与 父组件数据
的 双向绑定,简化代码
特点:prop属性名,可以 自定义
,非固定为 value
场景:封装弹框类的基础组件, visible属性
true显示 false隐藏
本质:就是 :属性名
和 @update:属性名
合写
案例
<template><div class="app">父组件<button @click="display">显示</button><!-- <Son :visible="isShow" 、@update:visible="isShow = $event" ></Son> --><!-- 上面和下面等价 --><Son :visible.sync="isShow"></Son> </div>
</template><script>
import Son from "./components/Son.vue";
export default {data() {return {isShow: false,}},methods: {display() {this.isShow = !this.isShow;}},components: {Son},
}
</script><style>
</style>
<template><!-- <div class="container" :style="{'display': visible ? 'block' : 'none'}"> --><div class="container" v-if="visible"><!-- 子组件 --><div class="form"><div class="header"><span>温馨提示</span> <!-- 这里update是定值 --><span @click="$emit('update:visible', false)">x</span></div><div class="body">确定退出吗</div><div class="footer"><button>确定</button><button>取消</button></div></div></div>
</template><script>
export default {props: {visible: Boolean},};
</script><style scoped lang="less">
.container::after{content: "";position: absolute;background-color: #e6e5e5;display: block;width: 100%;height: 100vh;top: 0;left: 0;z-index: 9;opacity: 0.5;
}
.form{position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);background-color: #d53737;width: 300px;height: 200px;z-index: 9999;.header{padding: 0 10px;height: 40px;line-height: 40px;display: flex;justify-content: space-between;span{&:nth-child(2){cursor: pointer;}}}.body{height: 124px;width: 100%;text-align: center;}.footer{display: flex;justify-content: space-around;}}</style>
运行结果