最新的vue3练习和vue3父组件向子组件传值
需要实现的功能是,点击列表(子组件),修改父组件的值,并改子组件变背景颜色。
效果图

这里用四种方法实现,应该还有第五种,第六种。
如果有更好的方式,欢迎大家留言提供。
页面
最上级页面
<template>
<div class="box">
<div>列表项目</div>
<MyList :list="dataList"></MyList>
</div>
</template>
<script>
import MyList from '../components/MyList.vue'
import {
reactive
} from "vue"
export default {
name: "index",
components: {
MyList
},
setup() {
let dataList = reactive([{
name: 'aaa',
age: 15,
isSelected:false
}, {
name: 'bbb',
age: 20,
isSelected:false
},
{
name: 'ccc',
age: 10,
isSelected:false
},
{
name: 'ddd',
age: 50,
isSelected:false
},
{
name: 'eee',
age: 88,
isSelected:false
}
])
return {
dataList
}
}
}
</script>
<style>
.box {
padding: 50px 20px;
}
</style>
父级页面
第一种方法是在元素上直接修改
<MyListItem v-for="(item,index) in list2" :listItem=item @selected="item.isSelected=$event.target.checked;item.name='大哥哥'" ></MyListItem>
这个表示赋值,直接修改了
item.isSelected=$event.target.checked;item.name='大哥哥'
参考,帮助理解
<template>
<div>
<input type="text" v-model="newValue">
</div>
</template>
<script>
export default {
props:{
value:{
type:String,
default:''
}
},
computed:{
newValue:{
get:function(){
return this.value
},
set:function(value){
this.$emit('input',value)//为了理解,看作是子组件中的方法
}
}
}
}
</script>
方便理解v-modelv-model = "msg" 可以翻译为:
:value="msg"
@input="msg=$events"//看作是父组件中调用
第二种是在setup里写方法改就如下面的页面
<template>
<!-- <MyListItem v-for="(item,index) in list2" :listItem=item @selected="item.isSelected=$event.target.checked;item.name='大哥哥'" ></MyListItem> -->
<MyListItem v-for="(item,index) in list2" :listItem=item @selected="mySelected"></MyListItem>
</template>
<script>
import MyListItem from "./MyListItem.vue"
import {
toRefs,
ref
} from 'vue'
export default {
name: "MyList",
props: ["list"],
components: {
MyListItem
},
setup(props, cxt) {
const list2 = ref(props.list)//获取从父级传来的值
//console.log(list2,"ddd")
//let num={ref(list2).value}
//console.log(num[0].name) //aaa
function mySelected(value, name) {//接受子组件传来的值,并改变数据
list2.value.map((item) => {//遍历寻找当前点击过的item项
if (item.name == name) {//相同表示选中了
item.isSelected = value.target.checked; //修改子项属性
}
})
}
return {
list2,
mySelected
}
}
}
</script>
<style>
</style>
子组件页面
第一种是 直接在元素上自定义方法,这里传了一个事件参数和一个item.name属性
<div :class='listItem.isSelected==true?"box-active":"box-unactive"' > <input type="checkbox" @change="$emit('selected',$event,listItem.name)" /> {{listItem.name}}--{{listItem.age}} </div>
这里把方法定义到元素上,而不是在setup里
<template>
<div class="box-item">
<div :class='listItem.isSelected==true?"box-active":"box-unactive"' > <input type="checkbox" @change="$emit('selected',$event,listItem.name)" /> {{listItem.name}}--{{listItem.age}} </div>
</div>
</template>
<script>
import { ref } from "vue";
export default{
name:"MyListItem",
props:["listItem"],
setup(props,cxt){
const listItem=ref(props.listItem)
return{
listItem
}
}
}
</script>
<style>
.box-item{
padding: 10px;
}
.box-active{
background: red;
}
.box-unactive{
background: white;
}
</style>
第二种也是在setup里写法,传递参数
页面
<template>
<div class="box-item">
<!-- <div :class='listItem.isSelected==true?"box-active":"box-unactive"' > <input type="checkbox" @change="$emit('selected',$event,listItem.name)" /> {{listItem.name}}--{{listItem.age}} </div> -->
<div :class='listItem.isSelected==true?"box-active":"box-unactive"' > <input type="checkbox" @change="sonClick($event,listItem.name)" /> {{listItem.name}}--{{listItem.age}} </div>
</div>
</template>
<script>
import { ref } from "vue";
export default{
name:"MyListItem",
props:["listItem"],
emits:["selected"],
setup(props,cxt){
const listItem=ref(props.listItem)//接受父级传来的参数
function sonClick(e,name){
cxt.emit('selected',e,name);
}
return{
listItem,
sonClick
}
}
}
</script>
<style>
.box-item{
padding: 10px;
}
.box-active{
background: red;
}
.box-unactive{
background: white;
}
</style>
刚刚接触vue3,如果发现代码有问题,欢迎大家指出来。
第三种方法
把子组件调用的方法作为属性,然后通过改变属性,去改变值,不知道这样描述对不对。
父组件
<template>
<!-- <MyListItem v-for="(item,index) in list2" :listItem=item @selected="item.isSelected=$event.target.checked;item.name='大哥哥'" ></MyListItem> -->
<MyListItem v-for="(item,index) in list2" :listItem="item" :selected="changeChecked" :numIndex="index"></MyListItem>
</template>
<script>
import MyListItem from "./MyListItem.vue"
import {
toRefs,
ref
} from 'vue'
export default {
name: "MyList",
props: {
list: {
type: Array //数据
}
},
components: {
MyListItem
},
setup(props, cxt) {
const list2 = ref(props.list) //获取从父级传来的值
function changeChecked(num) {
let item = list2.value[num] //获得选中的项
item.isSelected = !item.isSelected //修改选中状态
}
return {
list2,
changeChecked
}
}
}
</script>
<style>
</style>
子组件
<template>
<div class="box-item">
<!-- <div :class='listItem.isSelected==true?"box-active":"box-unactive"' > <input type="checkbox" @change="$emit('selected',$event,listItem.name)" /> {{listItem.name}}--{{listItem.age}} </div> -->
<div :class='listItem.isSelected==true?"box-active":"box-unactive"'> <input type="checkbox"
@change="selectedItem" />
{{listItem.name}}--{{listItem.age}}
</div>
</div>
</template>
<script>
import {
ref
} from "vue";
export default {
name: "MyListItem",
props: {
listItem: {
listItem: Object
},
selected: {
type: Function //方法作为属性传过去
},
numIndex: {
type: Number //索引ID号属性
}
},
setup(props, cxt) {
const listItem = ref(props.listItem) //接受父级传来的参数
//点击方法然后调用属性去改变值
function selectedItem() {
props.selected(props.numIndex); //调用父级方法和属性
}
return {
listItem,
selectedItem
}
}
}
</script>
<style>
.box-item {
padding: 10px;
}
.box-active {
background: red;
}
.box-unactive {
background: white;
}
</style>
第四种方法使用
<template>
<!-- <MyListItem v-for="(item,index) in list2" :listItem=item @selected="item.isSelected=$event.target.checked;item.name='大哥哥'" ></MyListItem> -->
<MyListItem v-for="(item,index) in list2" :listItem=item @selected="mySelected"></MyListItem>
</template>
<script>
import MyListItem from "./MyListItem.vue"
import {
toRefs,
ref,
provide
} from 'vue'
export default {
name: "MyList",
props: ["list"],
components: {
MyListItem
},
setup(props, cxt) {
const list2 = ref(props.list)//获取从父级传来的值
//console.log(list2,"ddd")
//let num={ref(list2).value}
//console.log(num[0].name) //aaa
function mySelected(value, name) {//接受子组件传来的值,并改变数据
list2.value.map((item) => {
if (item.name == name) {
item.isSelected = value.target.checked; //修改子项属性
}
})
};
//第四种方法
const xuanzhong=(value,name)=>{ //匿名方法
list2.value.map((item) => {
if (item.name == name) {
item.isSelected = value.target.checked; //修改子项属性
}
})
}
provide('xuanzhong',xuanzhong);//传递数据
return {
list2,
mySelected
}
}
}
</script>
<style>
</style>
子组件
<template>
<div class="box-item">
<!-- <div :class='listItem.isSelected==true?"box-active":"box-unactive"' > <input type="checkbox" @change="$emit('selected',$event,listItem.name)" /> {{listItem.name}}--{{listItem.age}} </div> -->
<div :class='listItem.isSelected==true?"box-active":"box-unactive"' > <input type="checkbox" @change="xuanzhong($event,listItem.name)" /> {{listItem.name}}--{{listItem.age}} </div>
</div>
</template>
<script>
import { ref,inject } from "vue";
export default{
name:"MyListItem",
props:["listItem"],
emits:["selected"],
setup(props,cxt){
const listItem=(props.listItem)//接受父级传来的参数
function sonClick(e,name){
cxt.emit('selected',e,name);
}
const xuanzhong = inject('xuanzhong') //接受父级方法
return{
listItem,
sonClick,
xuanzhong
}
}
}
</script>
<style>
.box-item{
padding: 10px;
}
.box-active{
background: red;
}
.box-unactive{
background: white;
}
</style>
这里几种方法,改天我再整理一下,写成大家都容易理解的。目前看有点绕!时间久了,自己都感觉奇怪!
子组件
<template>
<view>
<view>
<u--input v-model="newDate" border="none" :placeholder="chyPlaceholder" @focus="selectShow">
</u--input>
</view>
<u-calendar :show="chyDateShow" :mode="mode" @confirm="confirm" :monthNum="chyMonthNum" :minDate="minDate" >
</u-calendar>
</view>
</template>
<script>
const d = new Date()
const year = d.getFullYear()
let month = d.getMonth() - 1
month = month < 10 ? `0${month}` : month
const date = d.getDate()
import props from './props.js'
export default {
name: 'chy-date-select',
data() {
return {
newDate: "",
mode: 'single',
minDate: `${year}-${month}-${date + 10}`, //设置最小值范围
chyDateShow:false,
}
},
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
methods: {
selectShow() {
//this.$emit("openShow",true);
this.chyDateShow=true;
},
confirm(e) {
this.chyDateShow = false;
//console.log(e, "console.log(e)");
this.newDate = e[0];
this.$emit("selectDateValue", this.newDate)
},
},
}
</script>
<style>
</style>
父组件里方法调用赋值 太完美了
@selectDateValue="(chyValue)=>{formCustomer.contractDate=chyValue}"
<chy-date-select chyPlaceholder="签约日期" :selectDate="formCustomer.contractDate" @selectDateValue="(chyValue)=>{formCustomer.contractDate=chyValue}"></chy-date-select>
这样子组件可以动态生成无数个也不会错乱了。

浙公网安备 33010602011771号