【问题标题】:CSS styling to remember a users votes (up and downvote)用于记住用户投票的 CSS 样式(赞成和反对票)
【发布时间】:2018-07-08 15:49:45
【问题描述】:

使用 Reactjs 和 Firebase,我有一个小型投票应用程序,可让您对条目投赞成票或反对票。登录后,您可以对条目进行投票(目前它们只是名称),并且它们从最多票到最少票对自己进行排序。当您将鼠标悬停在投票图标上时,它们会改变颜色,如下所示:
普通:

悬停:

.downVote {
 align-items: center;
 font-size: 1.0em;
 padding-top: 2px;
 margin-right: 3px;
 float: right;
 color: #fb655a;
 cursor: pointer;
}

.downVote:hover {
 border-width: 0px;
 background-color: #fb655a;
 color: #000;
}

我想找到一种方法在投票后保持悬停属性处于活动状态——这是一个:active(?) 状态,并让 Javascript 或 Firebase 记住为该用户保持投票图标处于该状态。因此,当用户对几个名字进行投票并稍后返回该页面时,他们将看到他们投票了哪些名字以及他们投票的内容。

我正在寻找如何实现这一目标的想法。

目前,在 firebase 中,我将用户的身份验证 ID (uid) 保存在他们投票的每个人的姓名中,1 或 -1 表示赞成或反对票。我确定可以使用该变量,但我不确定如何将其绑定到 JavascriptCSS

提前感谢您的任何想法。


编辑


Firebase 布局:

所以对于这个用户 vKl6r...(在这种情况下是我),当我登录时,我应该看到名为 Test 的人旁边按下了赞成按钮,因为存储了一个 1。

这里是每个可以被投票的人的名字的布局(带有投票图标)

    handleUpvote(id){
    this.props.upvotePlayer(id)
}

handleDownvote(id){
    this.props.downvotePlayer(id)
}

render(props){
    return(
        <div className="player fade-in">
            <span className="vote up"
            onClick={() => this.handleUpvote(this.playerId)}>
            &#9650;
            </span>
            <p className="playerContent">{this.playerContent}</p>
            <span className="vote down" 
            onClick={() => this.handleDownvote(this.playerId)}>
            &#9660;
            </span>

        </div>
    )
  }
}

【问题讨论】:

  • 对于这个问题最好把这个图标做成一个组件,然后在上面设置onClick React事件
  • 你能发布你的 React 或 JS 代码吗?
  • 如果您的 html 使用自定义属性,您可以使用 css 为特定元素着色: [vote-status="1"] { background-color: red; }

标签: javascript css reactjs firebase firebase-realtime-database


【解决方案1】:

一般的想法是为您希望按钮在被投票时的外观创建一个 CSS 类,然后如果您的投票数据库对象包含按钮中的名称,则有条件地将 className 应用于按钮。

CSS 类选择器将与您现在拥有的悬停选择器相同:

.alreadyVotedOn {
 border-width: 0px;
 background-color: #fb655a;
 color: #000;
}

根据按钮是否被投票,有条件地将此类名称应用于按钮:

<button className={{this.state.votedOn[name] === -1 ? 'alreadyVotedOn' : null}}>▼</button>

我使用this.state.votedOn[name] === -1 来检测是否有人投票,因为听起来您有一个对象,其中包含用户在您的 Firebase 中某处投票的所有人员姓名。

为此,您需要将该对象加载到组件中并将其存储在键“votedOn”下的状态中。您可以通过 componentDidMount 中的数据库调用来执行此操作,或者如果您使用的是 redux 或 mobx,则将数据传入。

真的很难提出最好的方法来做到这一点,因为我们不了解数据是如何形成的,如何将其拉入组件或组件代码是什么样的。如果您可以共享数据库中相关块的屏幕截图和组件代码,我们会更加有用。

【讨论】:

  • 感谢您的想法。我在原始帖子中分享了带有 firebase 布局的屏幕截图,以及生成要投票的人和投票图标的代码并给出了一个类。 firebase 布局有每个可以被投票的人(玩家),然后在每个玩家内部,有一个名为voters 的孩子,它具有对该玩家投赞成票或反对票的所有用户的唯一 ID。感谢您的帮助。
【解决方案2】:

我不确定你是如何传递道具的,但如果this.playerContent 对应于屏幕截图中的字符串“test”,那么你组件中的this.voters 应该对应于已投票的对象。

如果正确,那么我将使用我的 uid 在此对象中搜索一个键,并检查该值是否为 1。

this.voters[myUid] === 1

您需要将您的 uid 作为道具传递。或者在 componentDidmount 中调用 auth() 以确保您可以访问您的 uid。

如果键存在并且值是 1,那么我添加一个 .alreadyVotedOn 类,正如我在下面的另一篇文章中提到的那样。您可以使用三元运算符或简单的 && 运算符...

this.voters[myUid] === 1 && 'alreadyVotedOn'

使用模板字符串将其弹出到你的upvote按钮上的className中:

<span 
  className={{`vote up ${this.state.votedOn[name] === 1 && 'alreadyVotedOn'}`}} 
  onClick={() => this.handleUpvote(this.playerId)}>
   &#9650;
</span>

这应该可以解决问题。

使用 -1 重复进行否决按钮。

您不必在 className 属性中全部执行此操作。您还可以添加自定义数据属性,例如之前评论中建议的@doppl3r。这个过程是一样的,只是让你的 className 属性更干净。

您可能希望使用按钮元素来确保语义正确,而不是使用跨度。使用按钮还可以让您访问 disabled 属性。您可以将相同的逻辑弹出到 disabled 属性中,以阻止人们多次投票。

希望对您有所帮助。

【讨论】:

  • 这有很大帮助。我在进行投票的 Player.jsx 中尝试访问 uid 时遇到问题,这是因为 auth() 和 uid 变量都在我的主 App.js 中。所以我看到你建议要么调用 auth 来获取那里的所有信息,要么将其作为道具传递。这很有帮助,谢谢。让我感到困惑的一件事是我没有 voters. 的道具我只是在 App.js 中做一个 let ref = firebase.database().ref('/players/' + playerId + '/voters'); 来访问选民孩子并检查 UID 是否存在以及它是否等于 1 或-1。这也可以在这里工作吗?
  • 是的,它也可以在这里工作。如果您已经在 app js 中调用数据,则无需两次调用相同的网络请求。把它作为道具传下去。您节省了网络请求,并且您的应用程序更快。
  • 这工作得很好——几乎和你说的完全一样。还有一个问题——我必须重新加载播放器对象的页面才能显示正确的投票图标更改。意思是,如果一开始投票赞成并突出显示,然后我点击反对票,我必须刷新才能进行更改。有没有办法在投票时刷新每个单独的玩家?我尝试在投票后强制重新渲染并调用 componentDidMount。
  • 这将取决于您如何调用 firebase 数据。如果您需要刷新,那么听起来您只调用了 .once(),您需要将调用切换到 .on(),以便它继续侦听更改。这应该有助于firebase.google.com/docs/database/web/… 或为此创建一个新的堆栈问题并将代码发布到您为投票对象调用 firebase 的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 2018-11-05
  • 2021-06-19
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 2010-12-04
相关资源
最近更新 更多