前端-v-model原理
目录
一.v-model原理
二.表单类组件封装
三.父组件v-model简化代码,实现子组件和父组件数据的双向绑定
一.v-model原理
原理:v-model本质上是一个语法糖。例如应用在输入框上,就是value属性和input事件的和写。
作用:提供双向的数据绑定
数据变了,视图中的数据也跟着变:value
视图中的数据变了,数据也跟着变@input
详解事件对象https://blog.csdn.net/weixin_52159554/article/details/151317800?spm=1001.2014.3001.5501
注意:$event用于在模板上,获取事件的形参
这里$event不可以直接替换为e,通过$event可以直接拿到当前事件的形参,而这个形参就是事件对象e
Vue 模板里写事件绑定时,比如 @click="myFn('参数1', '参数2')"
,Vue 会把你写的内容直接当作一段 JS 表达式来处理,它不会自动把事件对象塞进去。
👉 所以你需要手动告诉 Vue:我要事件对象! —— 这时候就得用 $event
。
二.表单类组件封装
父传子:数据应该是父组件props传递过来的,v-model拆解绑定数据
子传父:监听输入,子传父传值给父组件修改
创建父子代码并通过v-model来将父组件中的选择响应给子组件:
<script lang="ts">
import {defineComponent} from 'vue'
import Father from '@/components/Father.vue'export default defineComponent({name: "GrandfatherComponent",components: {Father},data() {return {key: '我是Grendfather的孙子',userInfo: {name: '张三',age: 99,},cityId: '102',}},provide() {return {key: this.key,userInfo: this.userInfo}},methods: {kit() {this.userInfo.name = '李四'console.log(this.userInfo)},handleClick(e) {console.log("事件类型是:", e.type); // clickconsole.log("点击位置是:", e.clientX, e.clientY);console.log("点击的元素是:", e.target);}}
})
</script><template><div>我是爷爷组件<div><button @click="kit">点击孙子的姓名发生变化</button></div><div><input type="text" v-model="userInfo.age"><input type="text" :value="userInfo.age" @input="userInfo.age = $event.target.value"/></div><div><button @click="handleClick">点击我</button></div><Father :cityId="cityId"></Father></div>
</template><style scoped lang="less"></style>
<script lang="ts">
import {defineComponent} from 'vue'
import Son from '@/components/Son.vue'export default defineComponent({name: "FatherComponent",components: {Son},props: {cityId: {type: String,required: true,default: ''}}
})
</script><template><div>我是父亲组件<select v-model="cityId"><option value="101">北京</option><option value="102">上海</option><option value="103">武汉</option><option value="104">深圳</option><option value="105">广州</option></select><Son></Son></div>
</template><style scoped lang="less"></style>
但是会报错:
原因是我们使用v-model来连接的,这样就会导致视图改变了,数据也会跟着改变,所以就会导致子组件修改了父组件中的数据,因为组件的独立性,所以是会报错的。
此时可以通过v-model的拆解来解决这个报错:
我们都知道v-model其实就是一个语法糖,是将数据绑定和事件响应绑定到了一起的,所以由此我们就可以得出解决办法:
使用:value来绑定数据 然后在使用@change="事件名"来实现v-model的效果
<script lang="ts">
import {defineComponent} from 'vue'
import Son from '@/components/Son.vue'export default defineComponent({name: "FatherComponent",components: {Son},props: {cityId: {type: String,required: true,default: ''}},methods: {changeCityId(e) {this.$emit('changeCityId', e.target.value)}}
})
</script><template><div>我是父亲组件<select :value="cityId" @change="changeCityId"><option value="101">北京</option><option value="102">上海</option><option value="103">武汉</option><option value="104">深圳</option><option value="105">广州</option></select><Son></Son></div>
</template><style scoped lang="less"></style>
三.父组件v-model简化代码,实现子组件和父组件数据的双向绑定
子组件中:props通过value接收,事件触发input
父组件中:v-model给组件直接绑定数据(:value + @input)
<script lang="ts">
import {defineComponent} from 'vue'
import Father from '@/components/Father.vue'export default defineComponent({name: "GrandfatherComponent",components: {Father},data() {return {key: '我是Grendfather的孙子',userInfo: {name: '张三',age: 99,},cityId: '102',}},provide() {return {key: this.key,userInfo: this.userInfo}},methods: {kit() {this.userInfo.name = '李四'console.log(this.userInfo)},handleClick(e) {console.log("事件类型是:", e.type); // clickconsole.log("点击位置是:", e.clientX, e.clientY);console.log("点击的元素是:", e.target);}}
})
</script><template><div>我是爷爷组件<div><button @click="kit">点击孙子的姓名发生变化</button></div><div><input type="text" v-model="userInfo.age"><input type="text" :value="userInfo.age" @input="userInfo.age = $event.target.value"/></div><div><button @click="handleClick">点击我</button><br><input type="text" v-model="cityId"></div><Father v-model="cityId"></Father></div>
</template><style scoped lang="less"></style>
<script lang="ts">
import {defineComponent} from 'vue'
import Son from '@/components/Son.vue'export default defineComponent({name: "FatherComponent",components: {Son},props: {value: {type: String,required: true,default: ''}},methods: {changeCityId(e) {this.$emit('input', e.target.value)}}
})
</script><template><div>我是父亲组件<select :value="value" @change="changeCityId"><option value="101">北京</option><option value="102">上海</option><option value="103">武汉</option><option value="104">深圳</option><option value="105">广州</option></select><Son></Son></div>
</template><style scoped lang="less"></style>