javascript - 如何获得按钮到材料 ui 列表的末尾和复选框到列表的开头?
问题描述
我的css不是很好,我面临很多困难......我正在尝试在material-ui的帮助下制作一个react todo应用程序......我的问题是我想在material-中显示待办事项ui 列表,在列表中的位置 1) 第一项将是复选框 2) 第二个待办事项文本 3) 第三个编辑和删除按钮
渲染 mui 列表的代码
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { todoDeleted, todoUpdated, todoCompleted } from '../Slices/TodoSlice';
import { Button, Checkbox, List, ListItem, ListItemSecondaryAction, ListItemText, makeStyles } from '@material-ui/core'
const useStyles = makeStyles({
listRoot: {
display: 'flex',
alignItems: 'center',
backgroundColor: '#fce4ec',
borderWidth: "1px",
borderColor: "#aaaaaa",
borderStyle: "solid",
borderRadius: "20px",
height: "35px",
margin: "5px 5px"
},
item: {
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
width: "500px"
}
})
export default function TodoItem({ todo, i }) {
const classes = useStyles()
const dispatch = useDispatch();
const [edit, setEdit] = useState(false);
const [text, setText] = useState(todo.text);
const handleUpdate = () => {
dispatch(
todoUpdated({
id: todo.id,
text,
})
);
if (edit) {
setText(todo.text);
}
setEdit(!edit);
};
return (
<div className={classes.listRoot}>
<List>
<ListItem className={classes.item}>
<ListItemText>
{todo.done ? (
<p>
<del>{todo.text}</del>
</p>
) : (
<h4>
{edit ? (
<input
type="text"
placeholder={text}
value={text}
onChange={(e) => setText(e.target.value)}
/>
) : (
todo.text
)}
</h4>
)}
</ListItemText>
<ListItemSecondaryAction>
<Checkbox
value={todo.id}
onChange={(e) => dispatch(todoCompleted(+e.target.value))}
defaultChecked={todo.done}
/>
<button
variant="contained" color="primary" edge='end'
onClick={() => handleUpdate()}
disabled={todo.done}
>
{edit ? 'Update' : 'Edit'}
</button>
<button
variant="contained" color="primary"
onClick={() => dispatch(todoDeleted(todo.id))}
>
Delete
</button>
</ListItemSecondaryAction>
</ListItem>
</List>
</div>
);
}
我想要第一项作为复选框,第二个待办事项文本和第三个按钮,请指导我
解决方案
这是您编辑的 CopePen,这是我修改的主要代码:
TodoList.js:
import { makeStyles, List } from "@material-ui/core";
import React from "react";
import { useSelector } from "react-redux";
import TodoItem from "./TodoItem";
const useStyles = makeStyles({
rootDiv: {
display: "flex",
flexDirection: "column",
justifyContent: "center",
marginLeft: "10px",
marginRight: "10px"
},
p: {
fontSize: "30px",
fontweight: "bolder"
}
});
export default function TodoList() {
const classes = useStyles();
const todos = useSelector((state) => state.TodoReducer);
const filter = useSelector((state) => state.viewFilterReducer);
const getVisibleTodos = (todos, filter) => {
switch (filter) {
case "SHOW_ALL":
return todos;
case "SHOW_ACTIVE":
return todos.filter((todo) => !todo.done);
case "SHOW_COMPLETED":
return todos.filter((todo) => todo.done);
default:
return todos;
}
};
const visibleTodos = getVisibleTodos(todos, filter);
return (
<div className={classes.rootDiv}>
{visibleTodos?.length === 0 ? (
<p className={classes.p}>No Todo Item Here</p>
) : (
<List>
{/*
I moved the list here, because you need to create only one list
and loop over you items
*/}
{visibleTodos.map((todo, i) => (
<TodoItem key={i} todo={todo} />
))}
</List>
)}
</div>
);
}
TodoItem.js:
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { todoDeleted, todoUpdated, todoCompleted } from "../Slices/TodoSlice";
import {
Button,
Checkbox,
List,
ListItem,
ListItemSecondaryAction,
ListItemText,
ListItemIcon,
makeStyles
} from "@material-ui/core";
/*
Since we fixed the issue about displaying multiple <List>,
you only need to style the items.
You can now properly define the height of your items, and set whatever you want as style,
the default flex layout is kept
*/
const useStyles = makeStyles({
item: {
height: "35px",
alignItems: "center",
backgroundColor: "#fce4ec",
border: "1px solid #aaaaaa",
borderRadius: "20px",
margin: "5px 5px"
}
});
export default function TodoItem({ todo, i }) {
const classes = useStyles();
const dispatch = useDispatch();
const [edit, setEdit] = useState(false);
const [text, setText] = useState(todo.text);
const handleUpdate = () => {
dispatch(
todoUpdated({
id: todo.id,
text
})
);
if (edit) {
setText(todo.text);
}
setEdit(!edit);
};
return (
<ListItem className={classes.item}>
<Checkbox
value={todo.id}
onChange={(e) => dispatch(todoCompleted(+e.target.value))}
defaultChecked={todo.done}
/>
<ListItemText>
{todo.done ? (
<p>
<del>{todo.text}</del>
</p>
) : (
<h4>
{edit ? (
<input
type="text"
placeholder={text}
value={text}
onChange={(e) => setText(e.target.value)}
/>
) : (
todo.text
)}
</h4>
)}
</ListItemText>
<ListItemSecondaryAction>
<button
variant="contained"
color="primary"
edge="end"
onClick={() => handleUpdate()}
disabled={todo.done}
>
{edit ? "Update" : "Edit"}
</button>
<button
variant="contained"
color="primary"
onClick={() => dispatch(todoDeleted(todo.id))}
>
Delete
</button>
</ListItemSecondaryAction>
</ListItem>
);
}
我主要改变了以下几点:
- 移动
<List>
了父组件中的组件。您正在为每个项目创建一个列表,这会产生多个 CSS 问题。注意你的组件应该显示什么! - 也删除了 CSS
listRoot
和div
节点。不再需要它了 - 将复选框移动为 listItem 的第一个子项,因此它尊重您要求的顺序
布局有自己的填充值。我只能强烈建议您保持原样,因为它很干净,但是如果您真的想将您的项目内容居中,您仍然可以为您的列表项目和第二个元素添加填充,例如:
const useStyles = makeStyles({
item: {
// ...
},
itemSpacing: { padding: 0 25% }
});
进而:
<ListItem className={[classes.item, classes.itemSpacing]}>
和 :
<ListItemSecondaryAction className={classes.itemSpacing}>
但是要非常小心,如果您的项目文本太长,它会中断,1)因为您为项目设置了硬编码高度,以及 2)因为ListItemSecondaryAction
在position: absolute
推荐阅读
- php - Laravel 中的文件上传路径不正确
- javascript - 在转到下一个命令之前,无法让 Javascript myFunction() 运行 var requiredFields = document.getElementById
- python - 如何在多个应用程序模板中使用 Django Haystack whoosh 搜索字段
- javascript - 我如何检查该函数是否存在于我的班级中
- xcode - 带有 Safari 视图控制器的客户端证书
- c - C编程中数组中缺少数字
- c# - 如何从源中获取 .pdf 文件以将其复制到目标的每日文件夹下?
- javascript - 用主页上的动态精选帖子内容替换静态内容 - Blogger Blogspot
- css - 我无法处理绝对位置的 z-index
- python - socket.recvmsg 忽略 ancbufsize,辅助数据