是的,添加 URL 会导致导航,因为没有逻辑来拦截该事件。
该链接正在调用一个 Ember 操作。Discourse 中的所有操作都是可扩展的。因此,它们在某种程度上就像自定义钩子。那么如何修改一个操作呢?好吧,让我们先看看它做了什么。
在 Github 或本地搜索该操作的名称。操作总是定义在 JS 文件中,并在 Handlebars 中被引用。我们想查看定义,所以我们将搜索范围缩小到 JS 文件。
你得到了四个文件。你应该查看哪一个?你想要自定义
discovery/topics.hbs
模板。所以
discovery/topics.js
是你想要查看的文件。
这些代码有帮助吗?没有,但我们现在知道操作定义在哪里了。所以,让我们修改它。
discovery/topics.js 是一个 Ember 类。你可以使用插件 API 中的一种方法来修改 Ember 类,叫做… modifyClass ![]()
我们已经知道想要修改的类了。它是 discovery/topics。我们需要知道它是什么类型的类。所以,让我们检查文件目录。
discourse/app/controllers/discovery/topics.js
它是一个控制器。
我们也知道想要修改该类中的 showInserted 操作。所以,我们从这里开始。
api.modifyClass("controller:discovery/topics", {
pluginId: 'sticky-new-topics-banner',
actions: {
showInserted() {
// 让我们做一些工作
}
}
});
然后,你可以添加任何你想要的代码,以便当用户点击“新主题”横幅时滚动窗口。我使用了类似这样的代码。
const listControls = document.querySelector(".list-controls");
listControls.scrollIntoView();
你可以在这里阅读更多关于 scrollIntoView() 的内容。
然后,你像这样将其添加到 plugin-api 方法中。
api.modifyClass("controller:discovery/topics", {
pluginId: 'sticky-new-topics-banner',
actions: {
showInserted() {
+ const listControls = document.querySelector(".list-controls");
+ listControls.scrollIntoView();
}
}
});
那么,我们完成了吗?没有。这会破坏 Discourse,因为你完全覆盖了该操作。点击链接现在会滚动到 list-controls 元素,但不会加载新主题。为什么?因为核心中的代码不再被应用。我的意思是,这部分内容
那么,如何修复呢?用这一行简单的代码
this._super(...arguments);
如果你只是想添加功能,而不需要复制核心中的任何代码。先做你的工作,然后添加那一行。它的作用只是确保核心中的代码被应用。
api.modifyClass("controller:discovery/topics", {
pluginId: 'sticky-new-topics-banner',
actions: {
showInserted() {
const listControls = document.querySelector(".list-controls");
listControls.scrollIntoView();
+
+ this._super(...arguments);
}
}
});
如果你测试这个,你会发现几乎所有东西都能很好地工作,除了… 标题与 list-controls 重叠了。为什么?因为标题被设置为 sticky。
你可以在 JS 中以多种方式修复这个问题——计算高度、获取偏移量、从 Discourse 导入辅助函数……等等。我不深入探讨这些。
最简单的方法是使用 CSS 和 scroll-margin-top,你可以在 这里 阅读相关内容。
所以,我们添加这个
.list-controls {
scroll-margin-top: calc(var(--header-offset) * 2);
}
用英语来说:当链接被点击时,滚动到 list-controls 的顶部减去 2 倍的标题高度,这样就不会重叠,并且下方有一点空间。
那么,让我们把所有这些结合起来。
common header 标签页
<script type="text/discourse-plugin" version="0.8">
api.modifyClass("controller:discovery/topics", {
pluginId: "sticky-new-topics-banner",
actions: {
showInserted() {
const listControls = document.querySelector(".list-controls");
listControls.scrollIntoView();
this._super(...arguments);
}
}
});
</script>
common CSS
#list-area {
// 移动端有不同的布局
.alert-info,
.show-more.has-topics {
position: sticky;
// Safari 有时没有前缀会很挑剔
position: -webkit-sticky;
top: var(--header-offset);
// 横幅应该在内容之上
z-index: z("header");
}
}
.list-controls {
scroll-margin-top: calc(var(--header-offset) * 2);
}