2017-03-15-react-css3-transition

汇智网学习react,今天学习,react中的CSS3 Transiton 按照例子做了一个仪表盘
Markdown

知识点

CSS3 Transition需要DOM属性的变化才能触发,所以我们需要将属性改变后的React 元素重新渲染到真实DOM上,才可以触发过渡效果。
react中使用 CSS3的步骤:
1. 为元素声明transition的样式
2. 设置属性的初始值,第一次渲染元素
3. 设置属性目标值,第二次渲染元素

实践

代码

  1. 使用了一个内部状态mounted 来实现第二次渲染:
  2. 当初次渲染完成功后,通过setState()方法我们触发 了再次渲染
  3. window.getComputedStyle() 这个方法的目的是刷新DOM的样式,以便确保之前设置的样式已经被应用到DOM 上了。

代码1:
height="400" width="600" scrolling="no" title="react CSS3 Transition-clock" src="//codepen.io/ziazan/embed/qrXvPN/?height=265&theme-id=0&default-tab=js,result&embed-version=2" allowfullscreen="true">See the Pen <a href="http://codepen.io/ziazan/pen/qrXvPN/">http://codepen.io/ziazan/pen/qrXvPN/</a>&#8216;&gt;react CSS3 Transition-clock by ziazan (<a href="http://codepen.io/ziazan">http://codepen.io/ziazan</a>&#8216;&gt;@ziazan) on <a href="http://codepen.io">http://codepen.io</a>&#8216;&gt;CodePen.


遇到的问题

问题1

React.findDOMNode(this.refs.ptr)

报错:

Uncaught TypeError: React.findDOMNode is not a function

这里找到了答案。正解是:在最新的react版本中,React.findDOMNode 改为ReactDOM.findDOMNode 修改之后没有报错了。

问题2

我想,既然是 要让指针转动,我设置指针的角度,不断地改变角度值不是就可以了吗?
所以我做了下面的修改
代码2

getInitialState: function() {
    return {
      value: 0, //速度值
      mounted: false, //是否已经挂到dom
      degree: -201
    };
render: function() {
    if (this.state.mounted) {
       this.setState({degree:(this.props.value / 220) * 265 - 201});
      //确保之前的样式生效
 window.getComputedStyle(ReactDOM.findDOMNode(this.refs.ptr)).transform;
    }
    var style = {
      transform: 'rotate(' + this.state.degree + 'deg)'
    }
    return (
     ...
    )
  }

无情报错:

Uncaught RangeError: Maximum call stack size exceeded
    at h._updateDOMProperties (react-dom.min.js:13)
    at h.updateComponent (react-dom.min.js:13)
    at h.receiveComponent (react-dom.min.js:13)
    at Object.receiveComponent (react-dom.min.js:14)
    at Object.updateChildren (react-dom.min.js:13)
    at h._reconcilerUpdateChildren (react-dom.min.js:14)
    at h._updateChildren (react-dom.min.js:14)
    at h.updateChildren (react-dom.min.js:14)
    at h._updateDOMChildren (react-dom.min.js:13)
    at h.updateComponent (react-dom.min.js:13)
    at h.receiveComponent (react-dom.min.js:13)
    at Object.receiveComponent (react-dom.min.js:14)

解决方案
我在render方法中打console.log('渲染第'+(++i)+ '次');发现,代码2渲染输出了N多次,直到Maximum call stack size exceeded。而代码1中只渲染输出两次
stackoverflow

You are calling this.props.incCount in componentWillReceiveProps which sets the state of the parent component and the effect will be that AddingTheFriend is rendered again, and this.props.incCount is called again. Hence the stack overflow.

这让我想起了

React要求我们使用 setState()方法来进行状态设置。这是因为,setState()方法会自动 地重新渲染组件。

由此我猜测试 效果过渡时,设置了state,引起ClockComp的多次渲染,然后就溢出了。


第二种实现方式(多余)

但是我还是觉得这个方案是可行的,然后我再看了看代码。发现好像逻辑怪怪的。
最后进行了修改。

render: function() {
    console.log('渲染第'+(++i)+ '次');
    console.log('时钟的角度'+this.state.degree);
    if (this.state.mounted) {
      //根据属性值计算旋转角度
      if(this.state.degree < (this.props.value / 220) * 265 - 201){
        this.setState({degree: ++ this.state.degree });
      }
      //确保之前的样式生效
  window.getComputedStyle(ReactDOM.findDOMNode(this.refs.ptr)).transform;
    }
    return (
    ...
    )
  }

效果是可以的,但是看日志发现,渲染了243次=.= ,应为是一次一次加的。再想想,看到了自己写的css

.pointer{
  position:absolute;
  left:150px;
  top:105px;
  transform-origin : 1px 45px;
  transition : transform 2s; /*注意这一行*/
}

发现自己完全没必要去 这么一点一点的增加角度来实现效果。(⊙o⊙)… 哎,我想多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值