2016-04-06 5 views
0

私が作業しているデザイナーは、複数列のテキストセットの行が本当に好きであると思います。それはかなり単純な電子ブックのためですが、私が高さを取得すると、時々正しくレンダリングされ、それ以外の時には正しく表示されません。参照用画像:React:テキスト要素の高さを取得する

enter image description here

だから、私は何をターゲットにしています(とも時間の一部を働いていること)をループにレンダリングヘッダー用であり、3つのヘッダの一番高いの高さを設定します。上記の画像では、関数は同様のビューをレンダリングするはずですが、ヘッダーのそれぞれがマージンを保持している必要があります。代わりに、マージンが削減されるように、すべて同じサイズに計算されています。残念ながら、孤児が1つしかないヘッダーでは(通常)高さが正しく計算されているようです。誰か良いアイデアはありますか?私のコードは以下の通りです。

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 { 
 

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

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

 
\t getItems(column, index) { 
 

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

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

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

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

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

 

 
export default branch(Columns, { 
 
\t cursors: { 
 
\t \t navOpen: ['navOpen'], 
 
\t } 
 
})

ColumnHeader.js -

import React from 'react' 
 
import { branch } from 'baobab-react/higher-order' 
 

 
class ColumnHeader extends React.Component { 
 

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

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

 
export default ColumnHeader

分かりやすくするための2番目の画像:enter image description here

+0

写真のすべての要素(アイコン、ヘッダー、サブヘッダー、テキスト)は、同じ高さ(必要に応じて)のように見え、内容は内側に一列に並んでいます。あなたは正確に何が違うのですか? – wintvelt

+0

各ヘッダー項目に1remの余白があるため、上記のようにしか表示されません。したがって、高さは実際には右側の2つのヘッダーを切り捨てていますが、マージンはそれらが配置されている全体のスペースが68ピクセルのようなものになるようにそれらをプロップしていますが、ヘッダーの実際の高さは42ピクセルヘッダーの実際の高さを下回ります。現実的には、3つはすべて高さが68ピクセルでなければなりません。たとえば、それぞれが正しく動作する場合は1remのマージンがあります。 – thesublimeobject

+0

申し訳ありませんが、私はまだそれを見ません。 CSSの高さ=コンテンツ+パディング+マージン。 heightが常に68pxの場合、マージンが異なっていても、すべてのヘッダーで同じ高さになります。そして、すべての要素が整列します。間違ったレイアウトの写真をもっとシェアできますか? – wintvelt

答えて

2

これはCSSの問題です: offsetHeightとheightには、CSSで異なる定義がありますが、これは理解しやすいものです。読んだものを使い、その値を使って他のものを設定すると、物事がうまくいかなくなります。これを行うために反応を使用するか他のフレームワークを使用するかは関係ありません。

  • offsetHeight =コンテンツ+パディング+ボーダー(しかしマージンを除く)
  • 高さ=コンテンツ+パディング+ボーダー+マージン

高さは除外マージンが読み込まれるので、小さすぎます。したがって、CSSはコンテンツを表示するためのマージンを犠牲にして補正します。例で

  • のあなたの高いヘッダーが0のパディング、10pxの上下の余白、及び2行と48pxの内容高さでコンテンツを有すると仮定する。
  • 合計高さは10 + 48 + 10 = 68pxです。
  • offsetHeightあなたは48ピクセルです。 (マージンは除く)
  • heightを48pxに設定します。マージンを含めて合計の高さが48ピクセルに設定されました。
  • これは間違った値です。正しい値は68ピクセルだったはずです。上部と下部のマージンを得るためにはJavaScript

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

    あなたが使用できるjQueryのか、バニラ:

あなたはupdateHeight()メソッドに高さを渡す前にoffsetHeightの上部と下部の余白を含める必要があり、修正するには。どちらもseparate thread on SO hereで説明されています。

より一般的には、同じ高さの行を得るための全体的なアプローチは非常に非効率的です。最初に列をレンダリングし、すべてのセルから高さを読み取り、高さを調整して再レンダリングします。おそらくCSSだけで高さの問題を解決するためのより良い全体的な解決策があります。
列の幅が同じで、すべてのセルの幅が同じであるように見えます。
cssだけを使用して各セルに同じ幅(%または固定)を与え、同じ行の各セルの高さが同じであることを確認することもできます。 HTMLテーブルまたはCSS flexbox(私は後者が好ましい)は、これを達成するためのオプションです。
次に、単純に1回のパスでレンダリングして、すべてのrefの読み込み、状態の更新とコードの再描画を失います。全体的なコードをよりきれいにし、より効率的にする。

+0

間違いなく、フレックスボックスの良いケース –

+0

私は実際にフレックスボックスを使用していますが、ローのような方法ではありません。私は時間がない私のデータ構造の大部分を書き直さなければならないので、私は実際に戻ってこれを行うことはできません。それにもかかわらず、これはもっと良い解決策になっているはずです。しかし、私はこれがCSSの問題であることに同意しません。レンダリング後に高さとマージンを別々に設定しても、同じ結果が得られます。失敗はレンダリング後に正確な高さを読み取ることにあります。そのため、私の質問は本質的に、私が推測するように、これらのDOM値をどのように反応させているのか、さらに良い方法があるかどうか疑問に思うのです。 – thesublimeobject

+0

help @wintveltありがとう。それはCSSの問題ではありませんでしたが、私はうまくやっていました。行グリッドが良い選択肢であることは間違いありません。データ構造を今すぐ書き直す時間がありません。これは、ほとんどのアプリを書いた後、デザイナーからのリクエストでした。 :// – thesublimeobject

関連する問題