-
v-model 的实质其实就是语法糖
从上图中我们可以看到v-model=”something”则表示将value值绑定在something上,当值发生改变时触发绑定的oninput事件。oninput事件绑定的函数是将触发oninput事件的目标(该input)的value值赋值给something这个变量。所以:
在vue3中要注意将 prop和event命名更改为modelValue和update:modelValue
主要的两个步骤:
1.自定义组件创建 props属性 modelValue
2.自定义组件触发update:modelValue事件,并把值传出去
- 下面我们先来封装一个最基础的 TestModel组件
// 自定义一个TestModel组件
<template>
<div>
<input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</div>
</template>
<script>
export default {
props: {
modelValue: {
type: String
}
}
}
</script>
- 使用组件
<testModel v-model="msg"></testModel>
等同于下面语法 默认传入一个modelValue 然后子组件接收这个modelValue
<testModel :modelValue="msg" @update:modelValue="msg = $event"></testModel>
// 引用TestModel组件
<template>
<h1>vue3中使用v-model {{msg}}</h1>
<testModel v-model="msg"></testModel>
<!-- 等同于下面语法 默认传入一个modelValue 然后子组件接收这个modelValue -->
<testModel :modelValue="msg" @update:modelValue="msg = $event"></testModel>
</template>
<script>
import { ref } from 'vue';
import testModel from './TestModel.vue';
export default {
components: {
testModel
},
setup(){
const msg = ref('')
return { msg }
},
}
</script>
- 有时候可能不想叫modelValue,也可以改成其他的名字,需要这样改写一下
// 父组件
<template>
<h1>vue3中使用v-model {{msg}}</h1>
<testModel v-model:msg="msg"></testModel>
</template>
子组件接收的props就要改成msg了
// 子组件
<template>
<div>
<input type="text" :value="msg" @input="$emit('update:msg', $event.target.value)" />
</div>
</template>
<script>
export default {
props: {
msg: {
type: String
}
}
}
</script>
- 双向绑定不一定必须是输入框组件,可以自定义各种各样的组件,比如通过click事件改变父组件的值,或者进一步封装 已有v-model功能的组件,比如进一步封装prism-editor
<template>
<div class="c-prism-editor">
<prism-editor
v-model="code"
class="my-editor"
:style="{height: _height}"
:highlight="highlighter"
:line-numbers="lineNumbers"
></prism-editor>
</div>
</template>
<script>
import { PrismEditor } from 'vue-prism-editor'
import 'vue-prism-editor/dist/prismeditor.min.css' // import the styles somewhere
// import highlighting library (you can use any library you want just return html string)
import { highlight, languages } from 'prismjs/components/prism-core'
import 'prismjs/components/prism-clike'
import 'prismjs/components/prism-javascript'
import 'prismjs/themes/prism-tomorrow.css' // import syntax highlighting styles
import { defineComponent, ref, reactive, onMounted, watch } from 'vue'
export default defineComponent({
name: 'c-prism-editor',
components: {
PrismEditor
},
props: {
height: String,
modelValue: String
},
emits: ['update:modelValue'],
setup(props, context) {
console.log(props)
let code = ref('')
let _height = props.height ? ref(props.height) : ref('300px') //默认300px
let lineNumbers = ref(true)
function highlighter(code) {
console.log(languages)
return highlight(code, languages.js) //returns html
}
watch(code, (newCode, prevCode) => {
context.emit('update:modelValue', newCode)
})
watch(props, (newCode, prevCode) => {
let {modelValue} = props
code.value = modelValue
})
return {
code,
lineNumbers,
highlighter,
_height
}
}
})
</script>
<style lang="less">
.c-prism-editor {
width: 100%;
.my-editor {
background: #2d2d2d;
color: #ccc;
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
font-size: 14px;
line-height: 1.5;
padding: 5px;
}
}
// optional
.prism-editor__textarea:focus {
outline: none;
}
</style>
使用
<div class="auto-center">
<c-prism-editor v-model="form.script" height="500px"></c-prism-editor>
</div>
以上就是封装vue3 实现v-model的知识点了,fzs原创,转载请注明出处