React:获取文本元素的高度

时间:2016-04-06 15:18:41

标签: javascript css reactjs

我正在使用的设计师非常希望多列圆柱文本的行相等。这是一个相当简单的电子书,但是当我达到高度时,有时它会正确呈现,而在其他时候它不会。供参考的图片:

enter image description here

所以,我所针对的(并且在某些时候也在工作)是渲染的标题循环并将高度设置为三个标题中最高的。在上图中,该函数应该呈现类似的视图,但每个标题保留其边距。相反,它已将它们全部计算为相同的大小,以便切割边距。不幸的是,似乎(通常)在只有一个孤儿的标题上,正确计算高度。有没有人有更好的想法?我的代码如下。

Columns.js(updateHeight是这里的重要功能) -



import React from 'react'
import { branch } from 'baobab-react/higher-order'
import classNames from 'classnames'
import _parseInt from 'lodash.parseint'
import _filter from 'lodash.filter'
import InlineSVG from 'react-inlinesvg'

// Column Components
import ImageContainer from './columns/ImageContainer'
import IconContainer from './columns/IconContainer'
import ColumnHeader from './columns/ColumnHeader'
import Content from './columns/Content'

class Columns extends React.Component {

	constructor(props, context) {
		super(props, context)
		this.state = {
			content: 0,
			header: 0,
		}
	}

	updateHeight(height, component) {
		if (window.innerWidth > 768 && window.innerHeight > 768) {
			if (height > this.state[component]) {
				this.setState({ [component]: height })
			} else {
				return false
			}
		} else {
			return false
		}
	}

	getItems(column, index) {

		let data = column[0] || column
		const icon = data.icon ? '/assets/icons/' + data.icon : null
		const image = data.bioImage ? '/assets/bio-photos/' + data.bioImage : null
		const ref = `column${ index }`

		return (
			<div className="column" key={ index } ref={ ref }>
				{ image ? <ImageContainer title={ data.title } image={ image } /> : null }
				{ icon ? <IconContainer icon={ icon } /> : null }
				<ColumnHeader 
					title={ data.title } 
					subtitle={ data.subtitle } 
					index={ index }
					updateHeight={ this.updateHeight.bind(this) }
					height={ index === undefined ? 'auto' : this.state.header } />
				<Content 
					content={ data.content } 
					updateHeight={ this.updateHeight.bind(this) }
					height={ index === undefined ? 'auto' : this.state.content } />
				{ this.props.type === 'team' 
					? <div className="team__social"><InlineSVG src="/assets/icons/linkedin.svg"></InlineSVG></div>
					: null
				}
			</div>
		)
	}

	render() {
		const data = this.props.data.columns || this.props.data
		const type = this.props.type
		const count = data.length || 1
		let columns = count > 1 ? data.map((column, index) => this.getItems(column, index)) : this.getItems(data, 1)

		let columnClasses = classNames({
			'columns': true,
			[`columns--${count}`]: true,
			'columns--icons': type === 'icons' ? true : false,
			'columns--team': type === 'team' ? true : false,
		})

		return (
			<div className={ columnClasses }>
				{ columns }
			</div>
		)
	}
}


export default branch(Columns, {
	cursors: {
		navOpen: ['navOpen'],
	}
})
&#13;
&#13;
&#13;

ColumnHeader.js -

&#13;
&#13;
import React from 'react'
import { branch } from 'baobab-react/higher-order'

class ColumnHeader extends React.Component {

	constructor(props, context) {
		super(props, context)
	}

	componentDidMount() {
		this.props.updateHeight(this.refs.header.offsetHeight, 'header')
	}
	
	render() {
		let { title, subtitle } = this.props
		let height = (this.props.height === 0) ? 'auto' : this.props.height
		return (
			<div className="column__header" ref="header" style={{ height: height }}>
				<h1 className="title">{ title }</h1>
				{ subtitle ? (<h2 className="subtitle">{ subtitle }</h2>) : null }
			</div>
		)
	}
}

export default ColumnHeader
&#13;
&#13;
&#13;

为清晰起见,第二张图片:enter image description here

1 个答案:

答案 0 :(得分:2)

这是一个CSS问题: offsetHeight和height在css中有不同的定义,这一点很重要。如果您使用read one并使用该值来设置另一个,那么事情就会出错。如果您使用react来执行此操作或任何其他框架,则无关紧要。

  • offsetHeight = content + padding + border( 但不包括保证金
  • height = content + padding + border + margin

因为读取的高度不包括边距,所以它太小了。因此,css通过牺牲余量来补偿以显示内容。

在一个例子中:

  • 让我们假设你的高标题的填充为0,顶部和底部的边距为10px,内容为2行,内容高度为48px。
  • 因此总高度为10 + 48 + 10 = 68px。
  • 你读的offsetHeight是48px。 (不包括保证金)
  • 然后将height设置为48px。由此产生的总高度(包括保证金)现在设置为48px。
  • 这是错误的值。正确的值应该是68px。

要修复,您需要在将高度传递给updateHeight()方法之前将顶部和底部边距包含在offsetHeight中:

componentDidMount() {
  // get topMargin and bottomMargin from DOM
  let heightPlusMargins = this.refs.header.offsetHeight + topMargin + bottomMargin;
  this.props.updateHeight(heightPlusMargins, 'header')
}

您可以使用jQuery或vanilla javascript来获取顶部和底部边距。两者都在separate thread on SO here中解释。

更一般地说:你获得相同高度的行的整体方法似乎非常低效。首先渲染列,然后从所有单元格中读取高度,然后调整高度并重新渲染。可能有更好的整体解决方案来解决css中的高度问题 看起来您的列宽度相等,因此所有单元格的宽度相等 您还可以按行(而不是按列)渲染,仅使用css为每个单元格指定相同的宽度(%或固定),并确保同一行中的每个单元格具有相同的高度。 HTML表格或CSS flexbox(我更喜欢后者)是实现这一目标的选项 然后你可以简单地渲染一次,并丢失所有的ref读取,状态更新和重新渲染代码。使整体代码更清晰,更高效。