根据 React 中的初始加载宽度动态格式化 img 宽度



我想根据其在 React 组件内的初始宽度或高度加载动态格式化img的宽度或高度,但以下两种都不起作用,第一个根本不渲染img,第二个无法找到some-img。我想做的事情可能吗?

const img = new Image()
img.onload = () => {
const height = img.height
const width = img.width
if (width < height) {
img.style.width = '105px'
} else {
img.style.height = '105px'
}
}
img.src = avatar.url
render () {
return (
img
)
}

const formatImg = () => {
const height = img.height
const width = img.width
if (width < height) {
document.getElementById('some-img').style.width = '105px'
} else {
document.getElementById('some-img').style.height = '105px'
}
}
render () {
return (
<img src={avatar.url} onload={formatImg()} id="some-img" />
)
}

我想你对new Imageonload有一些误解.

第一个代码,要呈现的内容应该是"HTML 元素"(至少看起来像),但img = new Image不是。所以你用可变img做的事情当然是行不通的。

第二个代码,onload = {formatImg()}表示分配给 onload prop 的 formatImg() 的返回值。你应该像这样编码:onload = {formatImg}.

最后一件事,如果我使用 React,我永远不会尝试直接操作 DOM 元素。相反,尽可能使用setState以便render循环运行。

像这样修改你的第二个:

const formatImg = () => {
const height = img.height
const width = img.width
if (width < height) {
this.setState({width: '105px', height: height + 'px'})
// document.getElementById('some-img').style.width = '105px'
} else {
this.setState({width: width + 'px', height: '105px'})
// document.getElementById('some-img').style.height = '105px'
}
}
render () {
const { width, height } = this.state;
return (
<img src={avatar.url} onload={this.formatImg} style={{width, height} />
)
}

第一个不起作用,因为 render() 方法不应该返回 DOM 元素。我想你误解了 React 应该如何工作。
你在 React 中使用的标签不是 html,也不是 html DOM 元素。标签是JSX,这是Babel理解的语法糖,并在生成捆绑javascript文件时转换为常规的javascript。
所以下面的JSX:

<h1>hello</h1>

变成以下 JavaScript:

React.createElement(
"h1",
null,
"hello"
);

这就是为什么你必须使用

import React from 'react';

即使它看起来不像你在任何地方使用它。
实际上,您实际上是在使用它,因为这就是JSX所代表的。

无论如何,回到上面的代码,createElement 的第一个参数"h1"告诉 React 您希望类型为"h1",第三个参数是"hello",因为这就是您希望孩子成为的样子。

因此,如果您的 JSX 是 :

<div><img></img></div>

那么编译的javascript是:

React.createElement(
"div",
null,
React.createElement("img", null)
);

如果你想玩JSX,你可以使用这个: https://babeljs.io/repl/

现在是重要的部分。当你使用 React.createElement 时,你不是在创建 DOM 元素。你甚至没有实例化 React 组件(如果你定义了自己的组件)。

你所做的只是给 React 一个模板结构,告诉 React 你打算做什么。React 会在它认为合适的时候处理实际的"做",以及它认为合适的方式。

我谈到的模板结构,例如:

React.createElement(
"h1",
null,
"hello"
);

很特别。
任何 React 组件的 return() 方法都必须返回该类型的对象。它不能返回任何其他内容,并且绝对不能返回 DOM 对象。

你的第二个代码块几乎可以工作,尽管它仍然不是在 React 中做这样的事情的首选方式。但是,如果您真的想这样做,则需要解决一些问题。

首先,"onload"属性应该拼写为"onLoad"。另外,您需要使用

this.formatImage

确保你不使用括号,否则代码将在 React 将你的图像放在页面上之前实际运行。现在它为什么要这样做?
因为 Babel 会改变你的 JSX:

<img onload={formatImg()} id="some-img" />

进入这个:

React.createElement(
"img", 
{ onload: formatImg(), id: "some-img" }
);

请注意,在您的代码中,"formatImg"函数实际上在作为参数传递到 React.createElement之前就运行了。(在创建模板之前,绝对在将其放到页面上之前。

最新更新