React CSS transition работает неправильно
Я написал приложение React, используя CSS-переходы. Но эти переходы не работают правильно в некоторых компонентах. В Мои приложения, только компоненты, которые движутся вверх, работают хорошо, те, кто движется вниз, перемещаются мгновенно без анимации. (Я хочу, чтобы они оба двигались с анимацией.)
вот CSS, который я использовал там:
div.canvas {
position: absolute;
top: 90px;
left: 60px;
width: 640px;
height: 480px;
border: 1px solid #999;
background: white;
}
div.canvas-rect {
position: relative;
margin-left: 20px;
margin-top: 10px;
height: 20px;
background: green;
transition: all 1s linear;
-moz-transition: all 1s linear; /* Firefox 4 */
-webkit-transition: all 1s linear; /* Safari 和 Chrome */
-o-transition: all 1s linear; /* Opera */
}
обновление:
Я также построил codepen.IO project показать проблема. Он имеет полный код этого демо-проекта.
Я попытался добавить запись журнала в componentDidUpdate
, componentDidMount
и componentWillUnmount
методы чтобы показать, создаются ли эти компоненты повторно или обновляются, он показывает, что все они обновляются (не создаются повторно или удаляются) каждую секунду.
4 ответов
Ну, после того, как я начал щедрость, потому что у меня также есть эта проблема, я, наконец, нашел то, что кажется проблемой.
когда вы используете абсолютную позицию (или относительную, как в вашем случае), если вы каждый раз перерисовываете весь список, React будет переупорядочивать элементы в DOM (как вы сказали, элементы не воссоздаются, просто обновляются). Но это создает проблему с переходами... по-видимому, если вы перемещаете элемент во время выполнения перехода, вы заканчиваете вырезание анимации.
Итак, для случаев, в которых вы хотите использовать position absolute, ключевой концепцией является визуализация контейнеров ваших элементов один раз (в этом случае просто divs) и изменение только внутреннего содержимого на основе нового порядка. Если вам нужно добавить больше элементов, просто добавьте их в конце.
Я изменил ваш код, чтобы он отражал то, что я говорю. Мой пример очень глуп, потому что я только что создал 4 ad-hoc divs, но он иллюстрирует идею: создайте как можно больше контейнеры, как вам нужно, но не используйте карту, которая воссоздает их каждый раз, или ваши переходы будут вырезаны.
https://codepen.io/damianmr/pen/boEmmy?editors=0110
const ArrList = ({
arr
}) => {
return (
<div style={{position: 'relative'}}>
<div className={`element element-${arr[0]} index-${arr[0]}`}>{arr[0]}</div>
<div className={`element element-${arr[1]} index-${arr[1]}`}>{arr[1]}</div>
<div className={`element element-${arr[2]} index-${arr[2]}`}>{arr[2]}</div>
<div className={`element element-${arr[3]} index-${arr[3]}`}>{arr[3]}</div>
</div>
);
}
Итак, проблема в том, как вы создаете статический список контейнеров и как вы перебираете этот список, чтобы первый контейнер отображал первый элемент ваших данных, второй контейнер-второй элемент и т. д.
надеюсь, что это поможет, эта проблема меня это тоже сводило с ума! :)
Если вы удаляете элемент из виртуального DOM, то react обновит его содержимое, поэтому вы не увидите анимации. Что вы можете сделать, это либо использовать react-transition-group или скажите вашему приложению подождать X МС перед обновлением dom после вызова события или использовать видимость для переключения между скрытым и отображением вместо того, чтобы полностью удалить его из DOM.
вы можете обмануть реагировать с помощью index
как ключ. Если вы думаете о el
и index
в качестве начальной позиции (индекс) и конечной позиции (el) элемент переместился в старую конечную позицию к концу перехода, и когда он там, он захватывается новой начальной позицией и (индекс) переключается в соответствии с новой настройкой. Это потому, что когда вы установите key
в элементе в react виртуальный DOM всегда будет интерпретировать его как один и тот же элемент. И ради этого, вы правы в настройке индекса как " id " в целом.
Я сделал рабочий пример только путем переключения index / el (и установки положения элемента в абсолют).
const {combineReducers, createStore} = Redux;
const { Provider, connect } = ReactRedux;
const ArrList = ({
arr
}) => (
<div>{
arr.map((el, index)=>
<div
key={""+index}
className={`element element-${el}` + ` index-${el}`}
>
{el}
</div>) }
</div>
)
const mapStateToArrList = (state) => {
return {
arr: state.appReducer.arr
}
};
const App = connect(mapStateToArrList, null)(ArrList);
const initialState = {
arr: [1, 2, 3, 4]
}
const appReducer = (state = initialState, action) => {
switch(action.type) {
case "tick":
return {
...state,
arr: _.shuffle(state.arr)
}
default:
return state
}
}
const reducer = combineReducers({
appReducer
})
const store = createStore(reducer)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
const dispatcher = () => {
store.dispatch({
type: "tick"
})
setTimeout(dispatcher, 1000)
}
dispatcher()
.element {
position: absolute;
height: 20px;
background: green;
margin-left: 20px;
margin-top: 20px;
text-align: right;
color: white;
line-height: 20px;
transition: all 1s ease-in;
-moz-transition: all 1s ease-in; /* Firefox 4 */
-webkit-transition: all 1s ease-in; /* Safari 和 Chrome */
-o-transition: all 1s ease-in; /* Opera */
}
.element-1 {
width: 20px;
}
.element-2 {
width: 40px;
}
.element-3 {
width: 60px;
}
.element-4 {
width: 80px;
}
.index-1 {
top: 20px;
}
.index-2 {
top: 40px;
}
.index-3 {
top: 60px;
}
.index-4 {
top: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.7.2/redux.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.6/react-redux.js"></script>
<div id="root"></div>
вы воссоздали DOM
элементы каждый раз.
Вы должны определить значение ключа collect.
Я изменил значение вашего ключа '' + el
to '' + index
.
<div key={'' + index} className={'element element-' + el + ' index-' + index} >
просто изменить