在vue3中自定义组件双向绑定语法的改变,使得写法和vue2大为不同。我们以element-plus的dialog组件为例。基于它。封装一个自己的对话框,同时介绍两种实现思路:
思路一:数据驱动型:
我们封装一个test-dialog组件:
import TestDialog from "@/components/Dialogs/TestDialog"
import { reactive, toRefs, ref, onMounted, watch } from "vue"
setup() {
const state = reactive({
flag: false
})
const open = () => {
state.flag = true
}
watch(() => state.flag, (val) => {
console.log("父组件监听flag:", val)
})
}
子组件:
title="提示" v-model="dialogVisble" width="30%" :before-close="close" > 这是一段信息 type="primary" @click="close" >确 定
import { ref, watch } from "vue"
export default {
name: "TestDialog",
components: {},
props: {
visible: {
type: Boolean,
default: false
}
},
setup(props, ctx) {
const dialogVisble = ref(false)
const close = () => {
ctx.emit("update:visible", false)
}
watch(() => dialogVisble.value, (val) => {
ctx.emit("update:visible", val)
})
watch(() => props.visible, (val) => {
dialogVisble.value = val
})
return {
dialogVisble,
open,
close
};
},
};
第二种思路:
类似直接操作dom,我们先通过ref拿到test-dialog组件的引用,每次点击打开按钮时,直接通过子组件去操作他内部的变量让它显示和隐藏
父页面:
import TestDialog from "@/components/Dialogs/TestDialog"
setup() {
const testDom = ref(null)
const openByParentMethod = () => {
testDom.value.dialogVisble = true
}
const closeByParentMethod= () => {
testDom.value.dialogVisble = false
}
return {
testDom,
openByParentMethod,
closeByParentMethod,
}
}
子组件:
title="提示" v-model="dialogVisble" width="30%" :before-close="close" > 这是一段信息 type="primary" @click="close" >确 定
setup(props, ctx) {
const dialogVisble = ref(false)
const open = () => {
dialogVisble.value = true
}
const close = () => {
dialogVisble.value = false
}
return {
dialogVisble,
open,
close
};
},
而对于vue2来说。实现这样的一个弹窗。则是通过如下方式:
而子组件中通过定义props:value,然后通过v-model 操控value来实现,如下:
1子组件在props中申明vaule,注意value名称是约定的不能写成其他的名称
2 子组件中通过 v-model="value"绑定改value
3关闭弹窗的时候,直接通过emit一个input事件来派发当前value的值。注意,这里只能写成input事件
(1)
v-model="value" @close="close" > 内容xxx
export default {
name: "selectCity",
components: {},
props: {
value: {
type: Boolean,
default: false
}
},
methods: {
close() {
console.log("close!!!!")
this.$emit("input", this.cityShow)
},
},
针对vue2我们通过一个inputNm组件来具体看一看
{{item1.name}}
¥ {{item1.vipPrice}}会员价
¥ {{item1.salePrice}}
没错InputNum 通过v-model绑定了我们购物车里的商品的数量。我们单独抽出这个组件进行计算
接下来我们看inputMum的具体实现
-
+
props里为什么是value?对。这就是vue多v-model处理时的约定俗成。默认value和input事件就是v-model的语法糖。当然如果你想换成其他值,则需要单独配置model选项。
特别注意:这里computed的使用。如果我们不是通过computed来引用props的值而是单独把value作为inputNum;里v-model的绑定值。这样页面会报错Avoid mutating a prop directly since the value will be overwritten whenever...因为vue默认遵守单向数据流的思想。不允许子组件直接去更改父组件的props的值。而通过computed我们可以巧妙的绕开这个限制