Elm中多textarea组件:如何识别被修改的组件?
解决Elm中多textarea更新时的识别问题
嘿,我完全懂你现在的困扰——用列表批量渲染多个textarea时,默认的onInput只能传回输入的字符串,根本没法区分到底是哪个组件触发了更新,想保存草稿就无从下手了对吧?其实解决思路很简单:给每个textarea绑定一个唯一标识,把标识和输入内容一起传给update函数就行。
下面给你具体的实现方案:
1. 定义带唯一标识的数据结构和消息类型
首先,确保你的草稿数据有唯一标识(比如自定义的id字段,或者用列表索引临时替代),然后扩展消息类型,让它能同时接收标识和新内容:
-- 单个草稿的结构,用id作为唯一标识 type alias Draft = { id : String , content : String } -- 整体模型 type alias Model = { drafts : List Draft } -- 消息类型:UpdateDraft 草稿ID 新内容 type Msg = UpdateDraft String String
2. 渲染时给每个textarea绑定标识
在渲染每个textarea的时候,不要直接用onInput UpdateDraft,而是用一个匿名函数把当前草稿的id和输入内容一起打包成消息:
view : Model -> Html Msg view model = div [] (List.map viewDraft model.drafts) viewDraft : Draft -> Html Msg viewDraft draft = textarea [ value draft.content -- 绑定当前草稿的内容,实现双向同步 , onInput (\newContent -> UpdateDraft draft.id newContent) -- 把ID和新内容一起发消息 ] []
3. 在Update函数中根据标识更新对应数据
收到UpdateDraft消息后,遍历草稿列表,找到对应ID的项并更新内容:
update : Msg -> Model -> Model update msg model = case msg of UpdateDraft targetId newContent -> { model | drafts = List.map (\draft -> if draft.id == targetId then { draft | content = newContent } -- 更新匹配到的草稿内容 else draft -- 其他草稿保持不变 ) model.drafts }
备选方案:用列表索引作为标识
如果你的草稿没有自定义ID,也可以用列表的索引来临时区分(注意:如果列表有排序、删除操作,索引会变化,这种情况更推荐用固定ID):
修改消息类型:
type Msg = UpdateDraft Int String -- 第一个参数是索引
渲染时用indexedMap获取索引:
view : Model -> Html Msg view model = div [] (List.indexedMap viewDraft model.drafts) viewDraft : Int -> Draft -> Html Msg viewDraft draftIndex draft = textarea [ value draft.content , onInput (\newContent -> UpdateDraft draftIndex newContent) ] []
Update函数中用索引匹配:
update : Msg -> Model -> Model update msg model = case msg of UpdateDraft targetIndex newContent -> { model | drafts = List.indexedMap (\currentIndex draft -> if currentIndex == targetIndex then { draft | content = newContent } else draft ) model.drafts }
这样就能精准定位到被修改的textarea,顺利保存每个草稿的内容啦!
内容的提问来源于stack exchange,提问作者kaskelotti
相关产品推荐
相关产品推荐

