---
title: 'react-dnd 拖拽'
date: 2021-08-23 13:57:00
---
![](https://img-blog.csdnimg.cn/20210823135611101.gif)
![](https://img-blog.csdnimg.cn/20210823135047242.png)
Index.js:
```javascript
import React from 'react'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { Form, Button, Collapse, Col, Row } from 'antd'
import Header from './Header'
import useList from './useList'
import { DndProvider } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'
import { Icon } from '../../../../components/light'
import { getComponentArr, getAttrFields } from './config'
import List from './List'
import BtnField from './BtnField'
const { Panel } = Collapse
function Index(props) {
const {
applicationTitle,
dataSource,
form,
formForAttr,
initValues,
initValuesForAttr,
tableId,
cardActiveId,
moveCard,
handleFinish,
handleFinishFailed,
handleAdd,
handleSave,
handleCardActiveId,
handleValuesChange,
handleDelete,
} = useList(props)
return (
<div className="m-admin-content">
<Header
applicationTitle={applicationTitle}
tableId={tableId}
onSave={handleSave}
></Header>
<div className="m-design-wrap">
<div className="m-design-sidebar">
<Collapse defaultActiveKey={['1', '2', '3']}>
<Panel header="通用字段" key="1">
<Row gutter={[2, 2]}>
<DndProvider backend={HTML5Backend}>
{getComponentArr().map((fieldInfo, index) => (
<BtnField key={index} fieldInfo={fieldInfo} onAdd={handleAdd} />
))}
</DndProvider>
</Row>
</Panel>
<Panel header="联系信息字段" key="2">
<Row gutter={[2, 2]}>
<Col span={8}>
<div className="m-component-item">
<div></div>
<div>敬请期待</div>
</div>
</Col>
</Row>
</Panel>
<Panel header="商品字段" key="3">
<Row gutter={[2, 2]}>
<Col span={8}>
<div className="m-component-item">
<div></div>
<div>敬请期待</div>
</div>
</Col>
</Row>
</Panel>
</Collapse>
</div>
<div className="m-design-content">
<Form
form={form}
labelCol={{ span: 4 }}
wrapperCol={{ span: 17 }}
initialValues={{ ...initValues }}
onFinish={handleFinish}
onFinishFailed={handleFinishFailed}
>
<DndProvider backend={HTML5Backend}>
<List
dataSource={dataSource}
cardActiveId={cardActiveId}
moveCard={moveCard}
handleCardActiveId={handleCardActiveId}
handleDelete={handleDelete}
/>
</DndProvider>
<Form.Item
wrapperCol={{ offset: 4, span: 17 }}
className="m-design-footer"
>
<Button type="primary" htmlType="submit" className="m-space">
<Icon name="submit" className="m-tool-btn-icon"></Icon>
提交
</Button>
<Button
className="m-space"
onClick={() => {
form.resetFields()
}}
>
<Icon name="reset" className="m-tool-btn-icon"></Icon>
重置
</Button>
</Form.Item>
</Form>
</div>
<div className="m-design-attr">
<Form
form={formForAttr}
labelCol={{ span: 8 }}
wrapperCol={{ span: 15 }}
initialValues={{ ...initValuesForAttr }}
scrollToFirstError={true}
onValuesChange={handleValuesChange}
id="m-set-application-modal-form"
className="m-set-application-modal-form"
>
{getAttrFields()}
</Form>
</div>
</div>
</div>
)
}
const mapStateToProps = (state) => {
return {}
}
const mapDispatchToProps = (dispatch) => {
return {
onSetState(key, value) {
dispatch({ type: 'SET_LIGHT_STATE', key, value })
},
onDispatch(action) {
dispatch(action)
},
}
}
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Index))
```
BtnField.js:
```javascript
import { useDrag } from 'react-dnd'
import { ItemTypes } from './ItemTypes'
import { Icon } from '../../../../components/light'
import { Col } from 'antd'
export default function BtnField({ fieldInfo, onAdd }) {
const [{ isDragging }, drag] = useDrag(() => ({
type: ItemTypes.BTN_FIELD,
item: { ...fieldInfo },
end: (item, monitor) => {
const dropResult = monitor.getDropResult()
if (item && dropResult) {
console.log(`${item.title} 加入 ${dropResult.name}`)
onAdd({fieldInfo})
}
},
collect: (monitor) => ({
isDragging: monitor.isDragging(),
handlerId: monitor.getHandlerId(),
}),
}))
const opacity = isDragging ? 0.4 : 1
return (
<Col span={8}>
<div
className="m-component-item"
ref={drag}
style={{ opacity }}
data-testid={`box-${fieldInfo.title}`}
onClick={() => onAdd({fieldInfo})}
>
<div>
<Icon name={fieldInfo.icon}></Icon>
</div>
<div>{fieldInfo.title}</div>
</div>
</Col>
)
}
```
config.js:
```javascript
import { Form, Input, Button } from 'antd'
import { FieldRequired } from '../../../../components/light'
//表格列字段
const getColumns = (props) => {
return [
{
title: 'ID',
dataIndex: 'id',
},
{
title: '字段名称',
dataIndex: 'title',
},
{
title: '英文名称',
dataIndex: 'dataIndex',
},
{
title: '表单组件名',
dataIndex: 'formComponentName',
render: (text) => {
return text ? text : '无'
},
},
{
title: '渲染函数名',
dataIndex: 'renderFunName',
render: (text) => {
return text ? text : '无'
},
},
{
title: '字段必填',
dataIndex: 'rules',
render: (text) => {
const result = Array.isArray(text) && text.length > 0 && text[0]
return result ? (result.required ? '是' : '否') : '否'
},
},
{
title: '表格展示',
dataIndex: 'isColumn',
render: (text) => {
return text ? '是' : '否'
},
},
// {
// title: '搜索',
// dataIndex: 'isSearch',
// render: (text) => {
// return text ? '是' : '否'
// },
// },
{
title: '添加/编辑',
dataIndex: 'isModalField',
render: (text) => {
return text ? '是' : '否'
},
},
{
title: '顺序号',
dataIndex: 'orderIndex',
render: (text) => {
return typeof text === 'number' ? text : '无'
},
},
{
title: '操作',
width: 220,
render: (record) => {
if (record.isSystem) {
return '系统字段'
} else {
return (
<div className="m-action">
<Button
className="m-action-btn"
size="small"
danger
onClick={() => props.onDelete(record)}
>
删除
</Button>
<Button
className="m-action-btn"
size="small"
onClick={() => props.onCheck(record)}
>
查看
</Button>
<Button
className="m-action-btn"
size="small"
onClick={() => props.onEdit(record)}
>
编辑
</Button>
</div>
)
}
},
},
]
}
//组件元素
const getComponentArr = () => {
return [
{
icon: 'input',
title: '单行文本',
formComponentName: "Input",
dataIndex: 'input',
renderFunName: "renderSpan"
},
{
icon: 'textarea',
title: '多行文本',
formComponentName: "TextArea",
dataIndex: 'textArea',
renderFunName: "renderSpan"
},
{
icon: 'number-input',
title: '数字',
formComponentName: "InputNumber",
dataIndex: 'inputNumber ',
renderFunName: "renderSpan"
},
]
}
//添加编辑查看对话框表单字段
const getAttrFields = () => {
return (
<>
<Form.Item
label="字段名称"
name="title"
rules={[
{
required: true,
message: '请输入字段名称!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="英文名称"
name="dataIndex"
rules={[
{
required: true,
message: '请输入字段名称!',
},
]}
>
<Input />
</Form.Item>
<Form.Item label="字段必填" name="rules">
<FieldRequired></FieldRequired>
</Form.Item>
</>
)
}
export { getColumns, getComponentArr, getAttrFields }
```
Header.js:
```javascript
import React from 'react'
import { Button } from 'antd'
import { withRouter, Link } from 'react-router-dom'
import { Icon } from '../../../../components/light'
function Header(props) {
const { applicationTitle, tableId, onSave } = props
return (
<div className="m-design-header">
<div className="m-design-header-title">
<Icon
name="goback"
title="返回"
className="m-set-application-header-icon"
onClick={() => props.history.go(-1)}
></Icon>
<span title={applicationTitle}>{applicationTitle}</span>
</div>
<div className="m-design-header-middle"></div>
<div className="m-design-header-action">
<Button type="primary" onClick={onSave}>
保存
</Button>
<Link to={`/light/formview?id=${tableId}`} target="_blank" style={{display: 'inherit'}}>
<Button>预览</Button>
</Link>
</div>
</div>
)
}
export default withRouter(Header)
```
ItemTypes.js:
```javascript
export const ItemTypes = {
LIST_ITEM: 'listItem',
BTN_FIELD: 'btnField' //'btnField',
}
```
List.js:
```javascript
import { useDrop } from 'react-dnd'
import { ItemTypes } from './ItemTypes'
import ListItem from './ListItem'
export default function List({
dataSource,
cardActiveId,
moveCard,
handleCardActiveId,
handleDelete,
}) {
const [{ canDrop, isOver }, drop] = useDrop(() => ({
accept: ItemTypes.BTN_FIELD,
drop: () => ({ name: '容器' }),
collect: (monitor) => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}),
}))
const isActive = canDrop && isOver
return (
<div
ref={drop}
className={`m-center-list-wrap ${isActive ? 'active' : ''}`}
>
{dataSource.map((card, index) => (
<ListItem
key={card.id}
index={index}
cardActiveId={cardActiveId}
card={card}
moveCard={moveCard}
onCardActiveId={handleCardActiveId}
onDelete={handleDelete}
/>
))}
</div>
)
}
```
ListItem.js:
```javascript
import { useRef } from 'react'
import { useDrag, useDrop } from 'react-dnd'
import { ItemTypes } from './ItemTypes'
import { Form, Input, Button } from 'antd'
import { getFormComponentArr } from '../../../../utils/tools'
export default function ListItem({
index,
cardActiveId,
card,
moveCard,
onCardActiveId,
onDelete,
}) {
const ref = useRef(null)
const [{ handlerId }, drop] = useDrop({
accept: ItemTypes.LIST_ITEM,
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
}
},
hover(item, monitor) {
if (!ref.current) {
return
}
const dragIndex = item.index
const hoverIndex = index
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return
}
// Determine rectangle on screen
const hoverBoundingRect = ref.current?.getBoundingClientRect()
// Get vertical middle
const hoverMiddleY =
(hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
// Determine mouse position
const clientOffset = monitor.getClientOffset()
// Get pixels to the top
const hoverClientY = clientOffset.y - hoverBoundingRect.top
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return
}
// Time to actually perform the action
moveCard(dragIndex, hoverIndex)
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex
console.log(hoverIndex)
},
})
const [{ isDragging }, drag] = useDrag({
type: ItemTypes.LIST_ITEM,
item: () => {
return { id: card.id, index }
},
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
})
const opacity = isDragging ? 0 : 1
drag(drop(ref))
//console.log(card)
const renderDom = () => {
if (card.isModalField) {
const result = getFormComponentArr().find(
(componentItem) =>
componentItem.formComponentName === card.formComponentName
)
return (
<div
ref={ref}
style={{ opacity }}
data-handler-id={handlerId}
className={`m-design-card ${
cardActiveId === card.id ? 'active' : ''
}`}
onClick={() => onCardActiveId({ id: card.id })}
>
<div className="m-design-card-info">
<Form.Item
key={card.id}
label={card.title}
name={card.dataIndex}
rules={card.rules}
>
{result ? result.component : <Input></Input>}
</Form.Item>
</div>
<div className="m-design-card-action">
<Button
className="m-action-btn"
size="small"
danger
onClick={() => onDelete(card)}
>
删除
</Button>
</div>
</div>
)
} else {
return null
}
}
return <>{renderDom()}</>
}
```
useList.js:
```javascript
import { useState, useEffect, useCallback } from 'react'
import Api from '../../../../api'
import { Modal, Form, message } from 'antd'
import update from 'immutability-helper'
import { getRouterSearchObj } from '../../../../utils/tools'
import { v4 as uuidv4 } from 'uuid'
const { confirm } = Modal
let currentDataSource = []
export default function useList(props) {
const [form] = Form.useForm()
const [formForAttr] = Form.useForm()
const [dataSource, setDataSource] = useState([])
const [applicationTitle, setApplicationTitle] = useState()
const [cardActiveId, setCardActiveId] = useState()
const [initValuesForAttr, setInitValuesForAttr] = useState({})
//获取路由参数
const routerSearchObj = getRouterSearchObj(props)
const tableId = routerSearchObj.id - 0
const addInitValues = {}
//搜索
const handleSearch = () => {
Api.light.fieldsSearch({ tableId }).then((res) => {
if (res.code === 200) {
let tempDataSource = res.data.fields.filter((item) => !item.isSystem)
setDataSource(tempDataSource)
setApplicationTitle(res.data.title)
if (Array.isArray(tempDataSource) && tempDataSource.length > 0) {
handleCardActiveId({
id: tempDataSource[0].id,
myDataSource: tempDataSource,
})
}
}
})
}
//拖动改变顺序
const moveCard = useCallback(
(dragIndex, hoverIndex) => {
const dragCard = dataSource[dragIndex]
setDataSource(
update(dataSource, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragCard],
],
})
)
},
[dataSource]
)
//添加新字段
const handleAdd = ({ fieldInfo }) => {
const orderIndexArr = currentDataSource.map((item) => item.orderIndex)
const orderIndex = Math.max.apply(Math, orderIndexArr) + 1
const id = uuidv4()
let tempValues = {
id,
dataIndex: `${fieldInfo.dataIndex}-${id}`,
isColumn: true,
isModalField: true,
orderIndex,
}
console.log({ ...fieldInfo, ...tempValues })
console.log(currentDataSource)
setDataSource([...currentDataSource, { ...fieldInfo, ...tempValues }])
}
//保存
const handleSave = () => {
console.log(dataSource)
const newDataSource = dataSource.map((item, index) => {
return { ...item, orderIndex: index + 1 }
})
console.log(newDataSource)
Api.light
.fieldsEditAll({ tableId, dataItem: newDataSource })
.then((res) => {
if (res.code === 200) {
message.success(res.message)
}
})
}
//删除
const handleDelete = (record) => {
console.log('删除, id:', record.id)
confirm({
title: '确认要删除吗?',
onOk() {
const newDataSource = dataSource.filter(item => item.id !== record.id)
setDataSource(newDataSource)
},
})
}
//添加或编辑
const handleFinish = (values) => {
console.log('Success:', values)
}
//校验失败
const handleFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo)
}
//设置当前card
const handleCardActiveId = ({ id, myDataSource = dataSource }) => {
setCardActiveId(id)
let currentItem = myDataSource.find((item) => item.id === id)
const rules =
Array.isArray(currentItem.rules) && currentItem.rules.length > 0
? currentItem.rules[0]
: {}
setInitValuesForAttr({ ...currentItem, rules })
}
//修改表单字段属性
const handleValuesChange = (changedValues, allValues) => {
const cardActiveIndex = dataSource.findIndex(
(item) => item.id === cardActiveId
)
let tempValues = {
rules: [allValues.rules],
}
dataSource[cardActiveIndex] = {
...dataSource[cardActiveIndex],
...allValues,
...tempValues,
}
setDataSource([...dataSource])
}
useEffect(() => {
formForAttr.resetFields()
// eslint-disable-next-line
}, [initValuesForAttr])
//挂载完
useEffect(() => {
handleSearch()
// eslint-disable-next-line
}, [])
//dataSource更新,同步更新currentDataSource,handleAdd函数中dataSource的值为空数组,这是一个bug
useEffect(() => {
currentDataSource = dataSource
}, [dataSource])
return {
form,
formForAttr,
initValuesForAttr,
dataSource,
applicationTitle,
addInitValues,
tableId,
cardActiveId,
handleSearch,
moveCard,
handleDelete,
handleFinish,
handleFinishFailed,
handleAdd,
handleSave,
handleCardActiveId,
handleValuesChange,
}
}
```
- vue模板里显示双大括号,不需要求值
- js正则表达式匹配闭合标签
- pagic Deno + React 驱动的静态网站生成器 入门
- antd Form.Item label添加解释信息
- deno可以通过url引入标准库,运行时自动下载,下载到哪里呢
- 如何查看github开源项目star趋势
- 使用deno开发post请求,get请求,监测文件变化自动重启(类似于nodemon)
- windows安装deno
- react 轮播图 react-slick
- display:flex 元素垂直居中,有间距,右对齐
- antd tabe表头出现遮挡
- url转二维码(js,qrcode)可以带logo
- react项目打包优化
- react-dnd 拖拽
- react-smooth-dnd 拖拽实例
- react中div的全屏与退出全屏
- 使用mock.js伪造图片数据,图片链接是枚举值
- moment生成前一天的时间
- Ant Design RangePicker预设常用的日期范围
- css文字太多时添加省略号
- node如何发生邮件,nodemailer
- sqlite3,在node中使用,轻量级数据库
- 使用fiddler修改网页的js文件
- 在控制台修改js变量的值,模拟异常,方便调试
- react路由懒加,项目经常上线导致没有刷新的用户出现js文件加载失败: ChunkLoadError: Loading chunk 42 failed.
- 前端向后端发送数据时,有时需要转数据格式,但是有时会得到意外的false数据
- js字符串处理,把img标签包裹在p标签里
- git代码回退
- antd 对话框、上传图片、轮播图结合在一起
- JavaScript 交换数组元素位置
- react报错:Can‘t perform a React state update on an unmounted component
- react 路由 404页面配置
- antd Tabs标签页 被隐藏时也渲染 DOM 结构
- antd表单不显示label和冒号
- 阻止Chrome开发者工具的控制台登录图像404错误
- create-react-app 区分环境 环境变量
- 在actionCreator中使用getState,数据格式是immutable
- 给树状数据添加层级id
- vscode中的正则搜索与替换演示,删除对象中不要的属性及属性值
- http-proxy-middleware做代理时,自定义复杂的匹配规则
- antd省市区级联
- axios封装
- react 封装antd menu组件,路由懒加载,可折叠,可配置显示和隐藏,刷新后选择正确的菜单,打开正确的submenu
- useHistory做页面跳转导航
- react-draft-wysiwyg富文本组件
- html转json json转html
- create-react-app 生成 report.html 可视化打包分析
- axios设置请求头实现post请求发送数据的格式(Form Data)
- url查询参数中的汉字如何解码
- React在body下追加全局组件并实现渲染更新
- js算法题,树状数据倒推
- 添加注释 使扁平的代码可以折叠
- create-react-app 关闭自动开启浏览器配置
- create-react-app 打包开启 gzip 压缩
- create-react-app 编译进度条配置
- create-react-app 生产环境去除sourcemap
- 通过cross-env改变create-react-app默认启动端口号
- create-react-app 修改 webpack output.publicPath
- React Hooks 父组件调用子组件的方法
- React Hooks 进入页面以后自动 focus 到某个输入框
- react hooks 太多的useState 显得很冗余,有没有什么规整的方法呢?
- react项目取消部分eslint检查
- 使用useMemo优化性能
- react的useEffect 第二个参数
- 如何使用 Postman Interceptor(可以拦截浏览器的请求到postman)
- react阻止事件冒泡
- 为何在 Modal 中调用 form 控制台会报错?
- prefetch 性能优化
- js 柯里化
- 在浏览器中使用JavaScript module(模块)
- github.io托管vue3.0项目
- 托管node项目平台介绍
- Ant Design of Vue 表单封装
- 并发执行异步事件,按顺序输出结果
- Promise
- vue cli 配置开发环境下的sourcemap
- vue3.0 在单个组件实例上创建多个 v-model 绑定
- Vue.js 3.0 的 Suspense组件
- Vue3.0 使用Teleport组件把对话框渲染的到指定位置
- 字符串包含双字节字符时如何遍历
- for in和for of遍历数组的索引
- vue3.0 组合式(Composition)API TodoList
- vue3.0 组合式API 加加减减
- Weak Set
- js数组去重
- vue3.0 组合式API(Composition API)
- 使用ES6数组解构实现变量交换
- ant-design-vue 日期区间选择设置默认时间
- 如何通过cdn方式使用阿里巴巴矢量图字体文件
- vue工作记录
- js数组去重
- 使用fetch请求数据
- react项目添加代理解决跨域
- js 控制 HTML5 audio标签 播放音频文件
- 1801A React 学习资料
- 1801A React
- TS入门课程资料
- TS入门
- vue3.0
- 项目实战【vue,react,微信小程序】(1710C)
- 课程资料
- 项目实战【vue,react,微信小程序】(1708E)
- 项目实战【vue,react,微信小程序】(1707B)
- 项目实战【vue,react,微信小程序】(1706C)
- node入门
- 使用react hook做一个小型完整项目(包括二级路由,动态路由,redux,tab切换,列表跳详情,登录, 守卫)
- chrome 突然出现 ERR_PROXY_CONNECTION_FAILED
- 项目实战【vue,react,微信小程序】(1705E)
- Vue(1706E)
- 加入购物车动画(css)
- React从入门到精通(1704B)
- React(1702H)文章管理-cms系统
- React(1702H)文件上传和分页查找
- React (1702H) 点击复制、滚动条、图形验证码、ridis、密码rsa加密、token、发邮件、文件上传、sql语句
- React(1702H)搭建架构,包裹redux、路由、api、拦截器、国际化
- 小程序购物车和搜索(1702H)
- 小程序(1702H)
- node + vue 实战项目(包含登陆、注册、找回密码、密码rsa加密、多语言、图形验证码、redis、路由、vuex、列表页、列表页内容动态添加、删除等等)
- 实训项目(1702H)
- 主流浏览器及其内核
- redux中间件redux-thunk的作用
- js sleep函数
- 基于react使用swaggerUI创建高质量的API文档
- js正则表达式验证合法的IP地址
- 前端使用jsencrypt.js做RSA加密
- JavaScript 执行机制(宏任务和微任务)
- 一行代码把网站变成黑白色调
- NPM依赖包版本号~和^的区别
- options请求是什么?
- 分支管理和自动化部署需求
- swiper 的左右箭头放到外面
- 使用Foxmail登录阿里企业邮箱(钉钉邮箱)
- 正则表达式 把所有的花引号替换为直引号 把字符串中所有单词的首字母都转换为大写
- react中getDerivedStateFromProps和componentDidUpdate配合使用
- js生成10个20-50之间的随机数(包含20和50)
- chrome jsonView插件安装 在浏览器地址栏里输入接口后返回的json数据格式化
- JS字符串使用占位符轻松实现拼接(来自react源码)
- linux + node + yarn + git + ssh + linux免密登录 + pm2自动部署
- react tab切换 第一次切换到某个页面时会请求数据,以后不会再请求数据
- 解决方案:sublime Text 3 无法安装插件有关问题 (JSON文件schema_version问题)
- ES6解构代替concat数组拼接
- 2019年最新web前端笔试题
- 考察js作用域、变量提升的面试题
- react书籍推荐
- React 父组件通过props控制子组件执行不同的方法进行渲染
- 科技感十足的大波浪动画(three.js)
- React性能优化 渲染20000多条checkbox组件,点击选择checkbox组件的时候特别卡,解决办法
- react网页多语言(react-intl-universal)
- 个人作品
- 程序员和产品经理的那些事
- three.js 根据不同的图片做不同的动画特效 科技感十足
- 互联网行业最佳产品开发流程 推荐!
- 类似于YouTube、Medium、知乎等网站使用的进度条插件 NProgress
- js模拟点击下载文件到本地
- Html5 js FileReader接口(读取本地txt的内容)
- react 搜集复选框组的状态
- 浏览器顶部loading(来自知乎)
- antd defaultExpandAllRows={true} 不起作用
- js获取页面选择的文本内容
- Can’t call setState (or forceUpdate) on an unmounted component
- js上传文件
- React 中setState({key:value}) key值动态变化,如何动态设置key的值
- classnames-plus 实例
- React tab切换页面
- react使用lazy()和Suspense实现根据路由进行代码分割
- react-loadable 使用高阶组件动态import组件,实现代码分割(code-splitting)
- react angular vue流行度对比
- react 服务端渲染(ssr) 框架 Next.js
- 超级字符串内class正则匹配替换 可以用于css modules
- React的setState()
- React的setState()
- React中setState
- 从头实现一个简易版的React虚拟dom和diff算法
- 如何理解虚拟DOM
- crate-react-app 之 css modules
- react-router-dom
- slider插件 滚动条插件 基于g2-plugin-slider.js修改
- React 在body上绑定事件以及阻止事件冒泡
- React 动态填加class
- React 点击按钮显示div与隐藏div
- g2曲线图 每条曲线有单独的选中效果和tooltip
- chrome扩展插件 1px 前端开发的html页面与设计师制作的psd对比
- echart自定义堆叠柱状图,每个矩形框都可以出现不同的tooltip内容
- overflow:hidden / scroll不会隐藏所有子元素
- echart旭日图
- 折线图tooltip固定位置
- aes.js加密
- 气泡图
- css斜切角 斜边 倒角
- g2基础柱状图
- sublime text 3 破解版下载
- CSS圆环百分比DEMO
- 曲线折线并存图
- g2雷达图
- nodejs如何引入jquery
- MutationObserver 监听页面的DOM元素是否发生了变化 (调试网页劫持)
- treeWalker
- npm 升级所有依赖包
- React中使用 ref 和 findDomNode
- React 创建对话框组件
- React中防止字符转义
- JSX添加注释
- redux和react-redux在react中的使用
- 动手实现 React-redux(三) Provider
- 动手实现 React-redux(二) mapDispatchToProps
- 动手实现 React-redux(一) connect 和 mapStateToProps
- Redux架构模式
- React context(不使用props,父组件给子组件传递信息)
- react组件书写规范
- 【react】利用prop-types第三方库对组件的props中的变量进行类型检测
- React 进入页面以后自动 focus 到某个输入框
- React 更新阶段的生命周期 componentWillReceiveProps->shouldComponentUpdate->componentWillUpdate
- React 生命周期 constructor->componentWillMount->render->componentDidMount->componentWillUnmount
- css3图片 变黑白 变模糊 调整饱和度等
- React 渲染列表数据
- React state 和 props总结 defaultProps(默认参数) 不可以在组件内部对props进行修改
- React 组件的 state 和 setState
- React中的事件绑定
- 网页loading效果 可以通过js控制旋转速度
- 纯css制作loading效果
- canvas时钟
- canvas实现动画 地球绕太阳公转 月球绕地球公转
- canvas基础三
- js中对String去空格
- 如何使上层div遮住的按钮依然可以点击 使用css实现( pointer-events:none )
- canvas基础二
- canvas基础一
- canvas点击事件
- jQuery判断当前页面是否被浏览
- jQuery.ajax设置请求头实现post请求发送数据的格式(Form Data和Request Payload)
- canvas制作圆角矩形(包括填充矩形的功能)
- css3+jQuery制作导航菜单(带动画效果)
- G2 实时刷新 流量监控图
- canvas制作呼吸灯
- canvas中的save和restore实例
- 使用window.requestAnimationFrame制作动画
- js已知正切值求角度
- css制作等腰三角形
- echart 柱状图 带箭头 调整柱子宽度 设置柱子颜色 hover时改变柱子颜色
- echart 柱状图 (精简)
- G2 面积图
- 按钮控制div显示和隐藏(动画)
- css绘制条纹背景 css画线 分割线 坐标线 栅格线
- Socket接口测试工具 (socket.io.js)
- LocalStorage如何存储JSON对象
- jQuery和css相结合制作动画----jQuery中animate方法不支持transform属性的解决方案
- jQuery深拷贝
- Canvas 通过改变渐变色渐变百分比位置做飞线效果
- IScroll 判断是否滚动到底部并加载更多数据
- css禁止文字被选择
- 时间戳(1532249295.179) 转日期格式(2018/07/22 16:48:15 179)
- iscroll.js右侧可滑动的菜单,点击每个菜单都会出现本菜单的详情
- canvas绘制的文字如何换行
- 移动端H5页面禁止长按复制和去掉点击时高亮
- 一列宽度不缩放,一列宽度弹性缩放,且超出后显示省略号
- js钩子机制(hook)
- mCustomScrollbar.js 漂亮的滚动条插件 适应内容自动更新
- axios.js 实例 -----$.ajax的替代方案
- 用 async/await 来处理异步实例
- immutable.js实例
- leaflet地图和飞线
- Canvas 通过改变渐变线的起始点做飞线效果
- css自动换行 包括url
- handlebars.js 模板引擎
- g2-plugin-slider.js 数据滚动条插件
- js拓扑图-vis插件
- js地图-leaflet
- css3 animation动画停留在最后一帧
- input输入手机号增加空格
- 百度输入框 获取焦点时 滚动到页面顶部的实现
- CSS3 transform-origin 设置旋转元素的基点位置
- $.extend()和$.fn.extend()
- $().each,$.each和arr.forEach对比解析
- ES6 assign
- ES6箭头函数this指向和arguments知识
- CSS多行文字超出隐藏加省略号
- css3实现雷达图
- js中参数都是按值传递的
- 移动端点击返回键 页面不刷新
- placeholder样式,ie input框眼镜图标,ie文档兼容模式
- React生命周期
- 业务代码编码规范-最佳实践
- 非常炫的文字效果
- 通过链接添加qq群
- React编程思想实例
- 禁止IOS长按复制粘贴
- 禁止文本框输入中文和空格(适用于密码输入框)
- swiper轮播图实例
- React入门
- js单例模式
- js判断是pc还是手机
- js实现xml转json和json转xml
- js实现xml转json
- margin重叠的解决办法
- 去除移动端按钮点击时的阴影和rem标签垂直居中
- 关于fiddler https 客户端 抓包配置
- javascript高级算法题
- 在一个数组中删除另一个数组存在的值
- 图片预加载,优化用户体验
- API接口规范
- 骰子的布局(flex)
- javascript中的作用域
- js引用类型和基本类型、隐式类型转换以及强制类型转换面试题
- css的content属性,以及如何通过css content属性实现css计数器?
- CSS实现:一个矩形内容,有投影,有圆角,hover状态慢慢变透明
- 百度元宵节动画
- HTML5的拖放功能
- 拖拽插件jquery.dad.js
- ::selection、多背景、border-image
- 有一个高度自适应的div,里面有两个div,一个高度100px,希望另一个填满剩下的高度(三种方案)
- CSS实现div的全屏自适应显示(两种方案)
- font-style: oblique文字斜体,display:inline-block显示间隙
- css制作三角形和小于12px的文字
- flex布局
- 倒影、阴影和文字特效 (reflect、shadow、text-shadow)
- 多列 响应式布局
- CSS3新增伪类
- translate3d(x,y,z)的用法
- 伪类选择器:checked将作用与input类型为radio或者checkbox以及option
- 对行内元素设置margin-top和margin-bottom是否起作用
- 个人作品
- 个人作品
- CSS3 渐变文字
- H5 tab切换页面
- 网页分享功能 支持 微信二维码 qq空间 qq好友 新浪微博 百度贴吧 豆瓣 人人
- js 分页
- js 去掉字符串中的非数字
- js replaceAll的实现
- H5弹出toast
- 元素自动滚动到可视范围内
- 超快的模板引擎 artTemplate.js
- 可拖动的弹窗
- 点击复制插件clipboard.js
- 阻止事件冒泡 阻止浏览器的默认行为
- 生成10个20-50之间的随机数 冒泡排序 数组乱序
- ES7的async/await
- 对一个数字每3位加一个逗号 千分符
- js获取当前时间
- 匹配域名
- 异步加载js文件
- 把URL参数解析为一个对象
- js连等赋值
- W3C盒模型和IE盒模型的区别
- 超出后显示省略号
- 当我们输入URL,按下回车发生了什么?
- CDN是什么?
- CSS实现隐藏滚动条同时又可以滚动
- 顶部固定 页面内容部分可以滚动
- H5对话框水平垂直居中
- 移动端调试神器(eruda)
- lazyload.js
- iscroll.js移动端滚动插件
- director.js 路由
- 移动端网页滑动到底部触发事件
- 移动端手指操控左右滑动的菜单
- em实例
- 雪碧图 移动端雪碧图
- rem实例
- 底部始终在文档末尾,当文档较长时跟随在文档末尾,当文档较短时在窗口底部
- css实现右侧固定宽度,左侧宽度自适应
- div带箭头提示框实例
- 中国省市区地址三级联动jQuery插件 Distpicker
- javascript不同类型数据之间运算的转换
- CSS选择器和优先级
- AJAX参数介绍
- ul li列表带图标浏览器兼容性解决方案
- 大段文字排版
- css background实例
- 上下左右中布局
- mustache.js使用笔记
- jQuery 鼠标滚轮插件 mousewheel
- 两边横线,中间标题
- CSS清除浮动 清除float浮动
- div对话框
- gulp+browserify前端模块化
- 使用gulp ES6转ES5
- JavaScript ES6 class实例
- vue+vue-validator 表单验证
- vue+vue-resource post请求
- 双向数据绑定的三种方式
- SeaJS 按需加载js模块
- CSS3 3D旋转立方体
- CSS3 transform
- CSS3动画 animation transition
- 响应式布局 媒体查询
- javascript 设计模式 发布订阅模式
- 跨域post请求 CORS
- HTTP错误代码 404 503 500
- div中img和a链接同时居中
- Generator 异步操作的同步化写法
- Generator的基本用法
- ECharts之柱状图 饼状图 折线图
- jQuery插件扩展实例
- less实例
- 理解requireJS原理,实现一个简单的模块加载器
- Vue自定义指令(directive)
- Vue 路由(router)
- Vue 父组件与子组件之间的通信
- null和undefined的区别
- javascript变量提升和函数提升
- javascript深拷贝的实现
- localStorage和sessionStorage用法总结及其区别
- ES6的Promise
- javascript冒泡排序,快速排序和堆排序
- js数组去重的算法实现
- DIV水平垂直居中
- CSS定位
- 使用Webpack ES6转ES5 实现模块化(import export)
- ES6入门
- Webpack入门教程
- jQuery和Vue的区别
- gulp使用指南
- RequireJS 按需加载js模块
- 页面加载时loading效果
- 事件委托,附实例
- 事件冒泡与事件捕获,附实例
- GET和POST的区别
- javascript之apply()和call()用法浅析
- javascript闭包浅析
- jsonp(跨域)-------可以运行的小实例!