一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情。
前言
在第14天的更文活动中,我们实现了父组件的数据传输给子组件。但是,不少小伙伴有代码洁癖,发现向子组件传值得时候会有报红的提示,如下图所示
今天我们来处理一下vs code中的报红问题和编写一个子组件传值给父组件的功能
解决父子组件传值报红的问题
其实要解决这两个报错很简单,就是给子组件集成Component的地方添加定义为参数为any的泛型代码。如下所示
import { View, Text } from "@tarojs/components";
import { Component } from "react";
import "./index.scss";
class ShopCartItem extends Component<any> {
constructor(props) {
super(props);
}
render() {
const item = this.props.item;
return (
<View className="shop-cart-item">
<Text>商品名称{item.name}</Text>
</View>
);
}
}
export default ShopCartItem;
我们分析一下component的源码,我们在没有添加泛型的时候,继承的component 类如下,可以看到我用红框标识的地方就是我们的写法
我们再看一下这个类中对应的构造器
可以看到props对应的类型为
Readonly<P>,我们添加any之后,就会触发或条件,返回any
子组件传值到父组件的功能开发
vue的子组件传参到父组件
老规矩,我们对比一下vue常用的字组件传值给父组件的方法
- 使用emit传参:父组引用子组件的时候,定义子组件的触发方法,例如
<child @reload=reload>,然后在子组件执行完某些方法之后,使用以下代码调用this.$emit('reload') - 使用状态管理器,这里大家可以参考我昨天的文章简单熟悉一下
- 不推荐的又low又呆瓜的做法:history.go和router跳转。我们都知道页面跳转的时候我们可以在页面初始化相关的地方进行数据渲染,所以可以直接通过切换到父级的路径可以实现简单的刷新方法(希望大家还是别用,容易被嘲讽)
实现
我们采用类似于emit的方法实现。我们模拟在编辑购物车数量页面修改购物车的数量,我直接先贴代码,在下面我会解释一下实现的逻辑
import { View, Text } from "@tarojs/components";
import { useEffect, useState } from "react";
import ShopCartItem from "./shop-cart-item";
import ShopCartEdit from "./shop-cart-edit";
import "./index.scss";
export default function ShopCart() {
interface shocartData {
id: string;
name: string;
price: number;
num: number;
}
const [shopCartList, setShopCartList] = useState([] as Array<shocartData>);
useEffect(() => {
setShopCartList([
{ id: "1", name: "第1个商品", price: 100, num: 4 },
{ id: "2", name: "第2个商品", price: 200, num: 3 },
{ id: "3", name: "第3个商品", price: 300, num: 2 },
{ id: "4", name: "第4个商品", price: 400, num: 1 },
]);
}, []);
const addItemNum = (id: string, num: number) => {
const newShopCartList = shopCartList.map((item) => {
if (item.id === id) {
item.num += num;
}
return item;
});
setShopCartList(newShopCartList);
};
return (
<View className="shop-cart">
{shopCartList.map((item) => (
<View>
<ShopCartItem item={item}></ShopCartItem>
<ShopCartEdit item={item} addIndexNum={addItemNum}></ShopCartEdit>
</View>
))}
<Text>共{shopCartList.length}条数据</Text>
</View>
);
}
shop-cart-edit/index.tsx代码
import { View } from "@tarojs/components";
import { Component } from "react";
import { AtButton } from "taro-ui";
import "./index.scss";
class ShopCartEdit extends Component<any> {
constructor(props) {
super(props);
}
render() {
const item = this.props.item;
return (
<View className="shop-cart-edit">
<AtButton onClick={() => this.props.addIndexNum(item["id"], 1)}>
点我{item["name"]}+1
</AtButton>
<AtButton onClick={() => this.props.addIndexNum(item["id"], -1)}>
点我{item["name"]}-1
</AtButton>
</View>
);
}
}
export default ShopCartEdit;
在购物车item中添加数量获取,可以看到我们点击+1的时候购物车数量会加1
原理
其实很简单,和父组件传参至子组件差不多,我们也是使用props来进行数据传递
大体的流程如上图所示
父子组将通过1和2步骤进行数据交互,第2步交互完之后,通过第3步调用方法修改值
结语
我们明天开始从首页挨着向后根据分许出来的需求进行开发,欢迎各位关键、点赞。明天讨论一下dom下拉过多的问题