---
title: 'react-dnd 拖拽'
date: 2021-08-23 13:57:00
---


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(跨域)-------可以運行的小實例!