需要實現的功能是,點擊列表(子組件),修改父組件的值,並改子組件變背景顏色。
效果圖

這里用四種方法實現,應該還有第五種,第六種。
如果有更好的方式,歡迎大家留言提供。
頁面
最上級頁面
<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>
這樣子組件可以動態生成無數個也不會錯亂了。
