Vuejs2 使计数器保持最新 [英] Vuejs2 keeping counter up to date
问题描述
我正在尝试使用 pusher
为聊天室中的用户列表动态更新计数器值.变量 usersCount
由 vue
实例维护并在模板中提供.vue
调试工具在下面的代码中将其显示为 undefined
.我没有将变量正确地从实例传递给模板.
chat-player-list
模板是这样调用的:
<div class="row"><chat-player-list ref="users" :users="users"></chat-player-list><小时/><div class="row"><div class="col-xs-12"><chat-player-messages ref="messages" :messages="messages"></chat-player-messages><h5>敌人闲聊</h5><chat-player-form v-on:chatmessagesent="addMessage" :player="{{ Auth::user() }}"></chat-player-form>
播放器都列出并渲染正常,另外其余的条件函数工作正常.只是 usersCounter
没有呈现.
我的 chat.js
代码包含主要的 vue
实例:
/*** 设置用于聊天的 Vue 组件*/$(document).ready(function(){Vue.component('chat-player-list', require('../components/chat-player-list.vue'));Vue.component('chat-player-messages', require('../components/chat-player-messages.vue'));Vue.component('chat-player-form', require('../components/chat-player-form.vue'));var chatPlayer = new Vue({el: '#sidebar-chat',数据:函数(){返回 {游戏:游戏,消息:[],用户:[],用户数:0};},创建(){this.fetchPlayers();this.fetchMessages();Echo.join(chat_channel).here((用户) => {$.each(users, function(index, value) {$('i#online-' + users[index].id).addClass('faa-ring animation player-online');});this.usersCount = users.length;}).joining((用户) => {$('i#online-' + user.id).addClass('faa-ring animation player-online');this.usersCount = this.usersCount + 1;}).离开((用户)=> {$('i#online-' + user.id).removeClass('faa-ring animation player-online');this.usersCount = this.usersCount - 1;}).listen('ChatMessageSent', (e) => {this.messages.unshift({消息:e.message.message,播放器:e.player});});},方法: {fetchPlayers() {this.users = game.progress.status.players_status;},fetchMessages() {axios.get(chat_get_route).then(响应 => {this.messages = response.data;});},添加消息(消息){this.messages.unshift(message);this.$nextTick(() => {this.$refs.messages.scrollToTop();});axios.post(chat_send_route,消息).then(响应 => {控制台日志(响应数据);});}}});});
在我的模板 chat-player-list.vue
中,我有:
<div class="col-xs-12"><h5>敌人在线</h5><span id="no-online-players" class="player-label pull-right">{{ usersCount }}</span><小时/><table id="new-game-opponents" class="new-game-opponents"><tr v-for="(user, index) in users" :key="index" :class="[isPlayerTurn(user.owner_id) ? playerTurnClass : '']"><td class="player_number"><div :class="['对手球员-' + index++]" v-once>{{ index++ }}</div></td><td class="玩家头像"><img :id="['player_avatar-' + user.owner_id]" class="setup_player_avatar" :src="[user.avatar]" v-once/></td><td class="player-name"><div :id="['player_nickname-' + user.owner_id]" v-once>{{ user.nickname }} <i :class="[isThisPlayer(user.owner_id) ? 'fa fa-user-circle-o' : 'hidden']" aria-hidden="true" style="color:DarkOrange;"></i></td><td class="player-status text-right"><div v-if="isPlayerTurn(user.owner_id)"><span :id="['player_turn-' + user.owner_id]" class="stage-label pull-right">{{ progress }}</span>
<div v-else><i class="fa fa-clock-o" aria-hidden="true" style="margin-right:5px;"></i>
</td><td class="player-status text-right"><i class="fa fa-comments" :id="['online-' + user.owner_id]" aria-hidden="true"></i></td><td class="player-status text-right"><div v-if="isHuman(user.owner_id)"><i class="fa fa-desktop" aria-hidden="true"></i>
<div v-else><i class="fa fa-user" aria-hidden="true" style="margin-right:2px;"></i>
</td></tr></tbody>
</模板><脚本>导出默认{道具:['用户','usersCount'],数据:函数(){返回 {playerTurnClass: '下一个玩家回合',nextPlayerId:game.progress.next_player_id,进度:game.progress.status.turn_status.current_stage,myPlayerId: my_player.id}},方法: {isPlayerTurn(thisUserId) {返回 thisUserId == this.nextPlayerId;},isThisPlayer(thisUserId) {返回 thisUserId == this.myPlayerId;},isHuman(thisUserOwnerId) {返回 thisUserOwnerId != 'ai';}}};
我错过了什么?谢谢!
解决方案数据不会自动传递给子组件,需要手动声明为prop.
<块引用>每个组件实例都有自己独立的作用域.这意味着您不能(也不应该)直接引用子组件模板中的父数据.数据可以通过 props 传递给子组件.
更新
你应该像 <chat-player-list ref="users" :users="users" :users-count="usersCount"></chat 一样绑定 usersCount
-玩家列表>
:a="b"
是 v-bind 的简写语法.这意味着传递当前实例的数据 b
作为名为 a
的 prop 传递给子组件.没有这个,即使 prop:['a']
存在,子组件也无法接收它.
所以只需添加 :users-count="usersCount"
.
正如 Vamsi 提到的,usersCount 应该作为 users-count
传递,参见:https://vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case
I am trying to get a counter value kept up to date dynamically for a list of users in a chat room using pusher
. The variable usersCount
is maintained by the vue
instance and served in a template. The vue
debug tool shows it as undefined
in the code below. I am not passing the variable correctly to the template from the instance.
chat-player-list
template is called like this:
<div class="modal-body" id="sidebar-chat">
<div class="row">
<chat-player-list ref="users" :users="users"></chat-player-list>
</div>
<hr/>
<div class="row">
<div class="col-xs-12">
<chat-player-messages ref="messages" :messages="messages"></chat-player-messages>
<h5>Enemies chit chat</h5>
<chat-player-form v-on:chatmessagesent="addMessage" :player="{{ Auth::user() }}"></chat-player-form>
</div>
</div>
</div>
The players all list and render OK, and additionally the rest of the conditional functions work OK. Just the usersCounter
not rendering.
My chat.js
code contains the main vue
instance:
/**
* Set up Vue components for chat
*/
$(document).ready(function()
{
Vue.component('chat-player-list', require('../components/chat-player-list.vue'));
Vue.component('chat-player-messages', require('../components/chat-player-messages.vue'));
Vue.component('chat-player-form', require('../components/chat-player-form.vue'));
var chatPlayer = new Vue({
el: '#sidebar-chat',
data: function () {
return {
game: game,
messages: [],
users: [],
usersCount: 0
};
},
created() {
this.fetchPlayers();
this.fetchMessages();
Echo.join(chat_channel)
.here((users) => {
$.each(users, function(index, value) {
$('i#online-' + users[index].id).addClass('faa-ring animated player-online');
});
this.usersCount = users.length;
})
.joining((user) => {
$('i#online-' + user.id).addClass('faa-ring animated player-online');
this.usersCount = this.usersCount + 1;
})
.leaving((user) => {
$('i#online-' + user.id).removeClass('faa-ring animated player-online');
this.usersCount = this.usersCount - 1;
})
.listen('ChatMessageSent', (e) => {
this.messages.unshift({
message: e.message.message,
player: e.player
});
});
},
methods: {
fetchPlayers() {
this.users = game.progress.status.players_status;
},
fetchMessages() {
axios.get(chat_get_route)
.then(response => {
this.messages = response.data;
});
},
addMessage(message) {
this.messages.unshift(message);
this.$nextTick(() => {
this.$refs.messages.scrollToTop();
});
axios.post(chat_send_route, message)
.then(response => {
console.log(response.data);
});
}
}
});
});
In my template chat-player-list.vue
I have:
<template>
<div class="col-xs-12">
<h5>Enemies online</h5>
<span id="no-online-players" class="player-label pull-right">{{ usersCount }}</span>
<hr/>
<table id="new-game-opponents" class="new-game-opponents">
<tbody>
<tr v-for="(user, index) in users" :key="index" :class="[isPlayerTurn(user.owner_id) ? playerTurnClass : '']">
<td class="player_number">
<div :class="['opponent player-' + index++]" v-once>{{ index++ }}</div>
</td>
<td class="player-avatar">
<img :id="['player_avatar-' + user.owner_id]" class="setup_player_avatar" :src="[user.avatar]" v-once/>
</td>
<td class="player-name">
<div :id="['player_nickname-' + user.owner_id]" v-once>
{{ user.nickname }}
<i :class="[isThisPlayer(user.owner_id) ? 'fa fa-user-circle-o' : 'hidden']" aria-hidden="true" style="color:DarkOrange;"></i>
</div>
</td>
<td class="player-status text-right">
<div v-if="isPlayerTurn(user.owner_id)">
<span :id="['player_turn-' + user.owner_id]" class="stage-label pull-right">{{ progress }}</span>
</div>
<div v-else>
<i class="fa fa-clock-o" aria-hidden="true" style="margin-right:5px;"></i>
</div>
</td>
<td class="player-status text-right">
<i class="fa fa-comments" :id="['online-' + user.owner_id]" aria-hidden="true"></i>
</td>
<td class="player-status text-right">
<div v-if="isHuman(user.owner_id)">
<i class="fa fa-desktop" aria-hidden="true"></i>
</div>
<div v-else>
<i class="fa fa-user" aria-hidden="true" style="margin-right:2px;"></i>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
props: ['users', 'usersCount'],
data: function () {
return {
playerTurnClass: 'next-player-turn',
nextPlayerId: game.progress.next_player_id,
progress: game.progress.status.turn_status.current_stage,
myPlayerId: my_player.id
}
},
methods: {
isPlayerTurn(thisUserId) {
return thisUserId == this.nextPlayerId;
},
isThisPlayer(thisUserId) {
return thisUserId == this.myPlayerId;
},
isHuman(thisUserOwnerId) {
return thisUserOwnerId != 'ai';
}
}
};
</script>
What did I miss? Thanks!
解决方案 Data won't be passed to child component automatically, you need manually declare it as prop.
Every component instance has its own isolated scope. This means you cannot (and should not) directly reference parent data in a child component’s template. Data can be passed down to child components using props.
Updated
You should bind usersCount
like <chat-player-list ref="users" :users="users" :users-count="usersCount"></chat-player-list>
:a="b"
is a shorthand syntax of v-bind. It means passing current instance's
data b
to the child component as a prop named a
. Without this, the child component cannot receive it even though prop:['a']
exists.
So just add :users-count="usersCount"
.
As Vamsi mentioned, usersCount should be passed as users-count
, See: https://vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case
这篇关于Vuejs2 使计数器保持最新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文
登录
关闭
扫码关注1秒登录
发送“验证码”获取
|
15天全站免登陆