我正在一个个人项目上,构建一些基本功能来处理PHP组件,以便可以用类似于React中的组件的方式来构建它们。我遇到了一些奇怪的行为,在这种情况下,如果我使用字符串插值内联渲染组件,则它会在代码中被调用的位置之前出现。通过将每个步骤作为自己的代码行运行,我能够使标记正确显示,但是我希望能够将这些组件包含在字符串中。为什么会发生这种乱序渲染?任何见识将不胜感激。
我试图返回包含的组件而不是回显它们,但是(也许因为使用了双引号?)它们根本不呈现。我还把这些组件串联在一起作为字符串。这是行不通的。如果我编写不同的代码行,并在每行之后以分号结尾,则可以得到预期的结果。
这就是我想要的工作:
echo "
<section class='videoInfo'>
<h1>{$props[$video]->getProperty(VIDEO_PROP::TITLE)}</h1>
<div class='secondary'>
<span class='viewCount'>{$props[$video]->getProperty(VIDEO_PROP::VIEWS)} views</span>
{$loader::render(COMPONENT::OPINION_CONTROLS)}
{$loader::render(COMPONENT::VIDEO_DETAILS)}
</div>
</section>
";
我也尝试过这样做,这导致与上面相同的错误输出:
echo "
<section class='videoInfo'>
<h1>{$props[$video]->getProperty(VIDEO_PROP::TITLE)}</h1>
<div class='secondary'>
<span class='viewCount'>{$props[$video]->getProperty(VIDEO_PROP::VIEWS)} views</span>" .
$loader::render(COMPONENT::OPINION_CONTROLS) .
$loader::render(COMPONENT::VIDEO_DETAILS) .
"</div>
</section>
";
这可以正常工作,但是编写起来比较麻烦:
echo "
<section class='videoInfo'>
<h1>{$props[$video]->getProperty(VIDEO_PROP::TITLE)}</h1>
<div class='secondary'>
<span class='viewCount'>{$props[$video]->getProperty(VIDEO_PROP::VIEWS)} views</span>";
$loader::render(COMPONENT::OPINION_CONTROLS);
$loader::render(COMPONENT::VIDEO_DETAILS);
echo "</div>
</section>
";
我希望输出HTML能够反映出回显的字符串。因此,最终输出应如下所示:
<section class="videoInfo">
<h1>Second Test</h1>
<div class="secondary">
<span class="viewCount">86 views</span>
<!-- includes javascript for handling like/dislike buttons -->
<script src="assets/js/opinions.js"></script>
<div class="controls">
<button class="opinion far fa-thumbs-up" onclick="like(this, 60)">
<span class="text">0</span>
</button>
<button class="opinion far fa-thumbs-down" onclick="dislike(this, 60)">
<span class="text">0</span>
</button>
</div>
<!-- includes javascript for handling edit/subscribe buttons -->
<script src="assets/js/videoInteractions.js"></script>
<section class="details">
<nav>
<a href="profile.php?username=testman">
<img src="assets/images/generic_profile.png" class="profilePic">
</a>
</nav>
<div class="uploadInfo">
<span class="uploader">
<a href="profile.php?username=testman">
testman
</a>
</span>
<span class="uploadDate">
Published on Jun 4, 2019
</span>
</div>
<button class="subscribe " onclick="subscribe("chan123", "testman", this)">
<span class="text">Subscribe 0</span>
</button>
<section class="description">
Testing view incrementing
</section>
</section>
</div>
</section>
这确实是我将每一步作为单独的代码行运行时得到的输出。但是,如果我使用字符串插值或串联,则组件加载顺序不正确。实际上,已加载的组件完全出现在videoInfo部分之前!
<button class="opinion far fa-thumbs-up" onclick="like(this, 60)">
<span class="text">0</span>
</button>
<button class="opinion far fa-thumbs-down" onclick="dislike(this, 60)">
<span class="text">0</span>
</button>
<nav>
<a href="profile.php?username=testman">
<img src="assets/images/generic_profile.png" class="profilePic">
</a>
</nav>
<div class="uploadInfo">
<span class="uploader">
<a href="profile.php?username=testman">
testman
</a>
</span>
<span class="uploadDate">
Published on Jun 4, 2019
</span>
</div>
<button class="subscribe " onclick="subscribe("chan123", "testman", this)">
<span class="text">Subscribe 0</span>
</button>
<section class="description">
Testing view incrementing
</section>
<h1>Second Test</h1>
<div class="secondary">
<span class="viewCount">87 views</span>
</div>
输出组件本身就是回显的字符串。他们看起来像这样:
(opinionControls)
echo "
<!-- includes javascript for handling like/dislike buttons -->
<script src='assets/js/opinions.js'></script>
<div class='controls'>
$likeButton
$dislikeButton
</div>
";
(videoDetails)
echo "
<!-- includes javascript for handling edit/subscribe buttons -->
<script src='assets/js/videoInteractions.js'></script>
<section class='details'>
<nav>
$profileButton
</nav>
<div class='uploadInfo'>
<span class='uploader'>
<a href='profile.php?username=$uploader'>
$uploader
</a>
</span>
<span class='uploadDate'>
Published on $formattedDate
</span>
</div>
$interactButton
<section class='description'>
{$props[$video]->getProperty(VIDEO_PROP::DESCRIPTION)}
</section>
</section>
";
嵌套回声是否会从顶级回声中冒泡?我正在努力解决这种问题。
我试图通过使嵌套组件返回字符串而不是执行回声来调整嵌套组件,但是我没有运气让它们完全以这种方式呈现。我尝试在返回的字符串周围使用单引号和双引号。像这样:
return '
<!-- includes javascript for handling like/dislike buttons -->
<script src=\'assets/js/opinions.js\'></script>
<div class=\'controls\'>
$likeButton
$dislikeButton
</div>
';
和
return "
<section class='videoInfo'>
<h1>{$props[$video]->getProperty(VIDEO_PROP::TITLE)}</h1>
<div class='secondary'>
<span class='viewCount'>{$props[$video]->getProperty(VIDEO_PROP::VIEWS)} views</span>
{$loader::render(COMPONENT::OPINION_CONTROLS)}
{$loader::render(COMPONENT::VIDEO_DETAILS)}
</div>
</section>
";
$ loader :: render()函数非常简单。它调用一个函数,该函数在已在应用程序中较早填充的组件上调用include()。相关的ComponentLoader函数如下:
// Load component into static primedComponents array as a key, with its value its props
public static function primeComponentWithProps(string $includesPath, array $props)
{
self::$primedComponents[$includesPath] = $props;
}
// Extract component and props from static array, then include it on the page
public static function render(string $includesPath)
{
$props = self::$primedComponents[$includesPath];
$args = [$includesPath, $props];
self::loadComponentWithProps(...$args);
// remove the component from the array of primed components once it has been rendered
unset(self::$primedComponents[$includesPath]);
}
/** used to import components that require props */
public static function loadComponentWithProps(string $includesPath, array $props)
{
// extract($props); // using extract() would allow props to be accessed directly by key names--but currently we are using a props array and accessing values by key to make it clearer what is going on in components which consume props
include($includesPath);
}