如何使用 $nextTick 在 vue.js 中呈现 Plotly 图表
How to render Plotly charts in vue.js with $nextTick
我正在尝试创建一个搜索引擎,用来自 plot.ly 的图表回答问题。但是一次只能显示一张图表。
我正在尝试使用 $nextTick 来解决它,但没有成功。
这是我的引擎的等效代码
<template>
<!-- eslint-disable -->
<v-container>
<v-layout text-xs-center wrap >
<v-flex ref="search" id="search_bar" xs12>
<img src="../../logo.png" height="200"><img>
<div>
<v-text-field ref= "search_bar" v-model="searchText" @keyup.enter="search" solo append-icon="search" hide-details single-line> </v-text-field>
</div>
</v-flex>
<v-flex ref="cards" id="cards" xs12>
<v-container grid-list-md>
<v-layout align-center justify-space-around row="2" fill-height id="layout">
<v-flex auto v-for = "item in vetRespostas" :key="item.id">
{{item.id}}
<textCard v-if= "item.cardType == 'text' " :textProps = "item.text" ></textCard>
<graphCard v-if= "item.cardType == 'graph' " :dataProps = "item.data" :layoutProps = "item.layout"></graphCard>
<tableCard v-if= "item.cardType == 'table' " :textProps = "textMock"></tableCard>
</v-flex>
</v-layout>
</v-container>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
/* eslint-disable */
import Plots_sitop from '../services/plots_sitop'
import tableCard from '../components/tableCard'
import graphCard from '../components/graphCard'
import textCard from '../components/textCard'
export default({
components: {
graphCard,
tableCard,
textCard
},
data() {
return {
searchText: '',
vetRespostas: [],
quests: [{
quest1: [{
pergunta: 'How many Keanu Reeves movies are 5 star?',
resposta: [
// primeiro card
{
id: 1,
cardType: "text",
text: "All of them"
},
// segundo card
{
id: 2,
cardType: "graph",
data: [{
x: ['Matrix','Point Break', 'Matrix Reloaded', 'John Wick', 'Jonh Wick 2','John Wick 3', 'Matriz Revoluntion', '47 Ronin', 'Dracula'],
y: [5,4,1,1,2,5,4,3,6],
type: "bar",
marker: {
color: ['rgb(0,140,69)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)']
}
}],
layout: {
title: "title",
xaxis: {
title: "x axys",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y axys',
showline: false,
}
}
},
// terceiro card
{
id: 3,
cardType: "graph",
data: [{
x: [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018],
y: [1, 2, 4, 5, 7, 3, 4, 5, 5],
type: "line",
marker: {
color: ['rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(0,140,69)']
}
}],
layout: {
title: "title",
xaxis: {
title: "title",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y axys',
showline: false,
}
}
},
// quarto card
{
id: 4,
cardType: "graph",
data: [{
x: ['1', '2', '3', '4','5'],
y: [5, 2, 2, 3, 1],
type: "bar",
marker: {
color: ['rgb(0,140,69)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)']
}
}],
layout: {
title: "title",
xaxis: {
title: "y axys",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'x axys',
showline: false,
}
}
}
],
}],
quest2: [{
pergunta: 'How many Keanu Reeves movies are 5 star?',
resposta: [
{
id: 1,
cardType: "text",
text: "Keanu Charles Reeves is a Canadian actor and musician."
},
{
id: 2,
cardType: "graph",
data: [{
x: ['Matrix','Matrix 2', 'Matrix 3', 'Point Break', 'John Wick','John Wick 2', 'John Wick 3', 'Constantine', '47 Ronin'],
y: [12,20,5,11,21,23,9,23,12],
type: "bar",
marker: {
color: ['rgb(0,140,69)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)']
}
}],
layout: {
title: "title",
xaxis: {
title: "xaxys",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y axys',
showline: false,
}
}
},
{
id: 3,
cardType: "graph",
data: [{
x: ['2001','2002','2003','2004','2005'],
y: [1, 2, 14, 5, 12],
type: "line",
marker: {
color: ['rgb(0,140,69)','rgb(0,140,69)','rgb(0,140,69)','rgb(0,140,69)','rgb(0,140,69)']
}
}],
layout: {
title: "title",
xaxis: {
title: "x",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y',
showline: false,
}
}
},
// quarto card 2 mock
{
id: 4,
cardType: "graph",
data: [{
x: ['NS-38', 'P-22', 'NS-14', 'NS-28','P-15'],
y: [2, 4, 3, 2, 1],
type: "bar",
marker: {
color: ['rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)']
}
}],
layout: {
title: "title",
xaxis: {
title: "x",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y',
showline: false,
}
}
}
]
}]
}],
}
},
methods: {
getResposta: function(){
var token = localStorage.getItem('token');
var data_request = {
'ambiguity_solved':{},
'has_ambiguity':false,
'request': this.searchText
};
if(token == null){
Plots_sitop.getToken().then(response => {
token = response.data.access_token
localStorage.setItem('token', token)
})
}
let headers = {'Authorization': 'Bearer ' + token, 'Content-Type' : 'application/json'};
Plots_sitop.postResposta(data_request, {headers}).then(
response => {
}, error => {
// Error
if (error.response.status == 401){
Plots_sitop.getToken().then(response => {
token = response.data.access_token
localStorage.setItem('token', token)
this.getResposta()
})
}
})
},
// Função utilizada quando os dados estão mockados
search: function(){
this.$refs.search.style.height = "auto";
var searchText = this.searchText;
var result = false;
this.vetRespostas = []
for(var i in this.quests[0]){
if(searchText == this.quests[0][i][0].pergunta){
result = true;
this.vetRespostas = this.quests[0][i][0].resposta;
console.log(this.vetRespostas)
}
}
if(result == false){
console.log('deu erro')
// this.$refs.erro.style.display = "inline";
}
}
}
})
</script>
<style>
#layout{
flex-direction: row;
}
#search{
height: 80vh;
display: flex;
flex-direction: column;
justify-content: center;
}
#card, #plot_1, #erro, #plot_2, #plot_3{
display: none;
}
</style>
这是我的组成部分:
<template>
<v-flex>
<v-card id = "plot" class="d-flex align-center" light height="400"></v-card>
</v-flex>
</template>
<script>
import Plotly from 'plotly.js'
export default {
data(){
return{
data: [{
x: false,
y: false,
type: false
}],
layout: {
title: false,
xaxis:{
title: false,
showgrind: false,
zeroline: false
},
yaxis: {
title: false,
zeroline: false
}
},
}
},
props: ['dataProps', 'layoutProps'],
mounted (){
this.data = this.dataProps
this.layout = this.layoutProps
Plotly.newPlot('plot',this.data,this.layout)
}
}
</script>
<style>
</style>
和
<template>
<v-flex>
<v-card class="mx-auto" dark v-model='text' color="rgb(0,140,69)" height="400">
<v-card-text class="display-2 text-xs-center font-weight-black"> {{text}}</v-card-text>
</v-card>
</v-flex>
</template>
<script>
export default {
data(){
return {
text: ''
}
},
props: ['textProps'],
mounted(){
this.text = this.textProps
}
}
</script>
<style>
</style>
我尝试在我的组件上这样做:
mounted (){
this.$nextTick(() => {
this.data = this.dataProps
this.layout = this.layoutProps
Plotly.newPlot('plot',this.data,this.layout) });
}
但是没有用。
我在我的 id 上使用 V-bind 解决了这个问题。
感谢@skirtle 的帮助。
我正在尝试创建一个搜索引擎,用来自 plot.ly 的图表回答问题。但是一次只能显示一张图表。
我正在尝试使用 $nextTick 来解决它,但没有成功。
这是我的引擎的等效代码
<template>
<!-- eslint-disable -->
<v-container>
<v-layout text-xs-center wrap >
<v-flex ref="search" id="search_bar" xs12>
<img src="../../logo.png" height="200"><img>
<div>
<v-text-field ref= "search_bar" v-model="searchText" @keyup.enter="search" solo append-icon="search" hide-details single-line> </v-text-field>
</div>
</v-flex>
<v-flex ref="cards" id="cards" xs12>
<v-container grid-list-md>
<v-layout align-center justify-space-around row="2" fill-height id="layout">
<v-flex auto v-for = "item in vetRespostas" :key="item.id">
{{item.id}}
<textCard v-if= "item.cardType == 'text' " :textProps = "item.text" ></textCard>
<graphCard v-if= "item.cardType == 'graph' " :dataProps = "item.data" :layoutProps = "item.layout"></graphCard>
<tableCard v-if= "item.cardType == 'table' " :textProps = "textMock"></tableCard>
</v-flex>
</v-layout>
</v-container>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
/* eslint-disable */
import Plots_sitop from '../services/plots_sitop'
import tableCard from '../components/tableCard'
import graphCard from '../components/graphCard'
import textCard from '../components/textCard'
export default({
components: {
graphCard,
tableCard,
textCard
},
data() {
return {
searchText: '',
vetRespostas: [],
quests: [{
quest1: [{
pergunta: 'How many Keanu Reeves movies are 5 star?',
resposta: [
// primeiro card
{
id: 1,
cardType: "text",
text: "All of them"
},
// segundo card
{
id: 2,
cardType: "graph",
data: [{
x: ['Matrix','Point Break', 'Matrix Reloaded', 'John Wick', 'Jonh Wick 2','John Wick 3', 'Matriz Revoluntion', '47 Ronin', 'Dracula'],
y: [5,4,1,1,2,5,4,3,6],
type: "bar",
marker: {
color: ['rgb(0,140,69)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)']
}
}],
layout: {
title: "title",
xaxis: {
title: "x axys",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y axys',
showline: false,
}
}
},
// terceiro card
{
id: 3,
cardType: "graph",
data: [{
x: [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018],
y: [1, 2, 4, 5, 7, 3, 4, 5, 5],
type: "line",
marker: {
color: ['rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(0,140,69)']
}
}],
layout: {
title: "title",
xaxis: {
title: "title",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y axys',
showline: false,
}
}
},
// quarto card
{
id: 4,
cardType: "graph",
data: [{
x: ['1', '2', '3', '4','5'],
y: [5, 2, 2, 3, 1],
type: "bar",
marker: {
color: ['rgb(0,140,69)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)']
}
}],
layout: {
title: "title",
xaxis: {
title: "y axys",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'x axys',
showline: false,
}
}
}
],
}],
quest2: [{
pergunta: 'How many Keanu Reeves movies are 5 star?',
resposta: [
{
id: 1,
cardType: "text",
text: "Keanu Charles Reeves is a Canadian actor and musician."
},
{
id: 2,
cardType: "graph",
data: [{
x: ['Matrix','Matrix 2', 'Matrix 3', 'Point Break', 'John Wick','John Wick 2', 'John Wick 3', 'Constantine', '47 Ronin'],
y: [12,20,5,11,21,23,9,23,12],
type: "bar",
marker: {
color: ['rgb(0,140,69)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)']
}
}],
layout: {
title: "title",
xaxis: {
title: "xaxys",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y axys',
showline: false,
}
}
},
{
id: 3,
cardType: "graph",
data: [{
x: ['2001','2002','2003','2004','2005'],
y: [1, 2, 14, 5, 12],
type: "line",
marker: {
color: ['rgb(0,140,69)','rgb(0,140,69)','rgb(0,140,69)','rgb(0,140,69)','rgb(0,140,69)']
}
}],
layout: {
title: "title",
xaxis: {
title: "x",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y',
showline: false,
}
}
},
// quarto card 2 mock
{
id: 4,
cardType: "graph",
data: [{
x: ['NS-38', 'P-22', 'NS-14', 'NS-28','P-15'],
y: [2, 4, 3, 2, 1],
type: "bar",
marker: {
color: ['rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)','rgb(192,192,192)']
}
}],
layout: {
title: "title",
xaxis: {
title: "x",
showgrid: false,
zeroline: false
},
yaxis: {
title: 'y',
showline: false,
}
}
}
]
}]
}],
}
},
methods: {
getResposta: function(){
var token = localStorage.getItem('token');
var data_request = {
'ambiguity_solved':{},
'has_ambiguity':false,
'request': this.searchText
};
if(token == null){
Plots_sitop.getToken().then(response => {
token = response.data.access_token
localStorage.setItem('token', token)
})
}
let headers = {'Authorization': 'Bearer ' + token, 'Content-Type' : 'application/json'};
Plots_sitop.postResposta(data_request, {headers}).then(
response => {
}, error => {
// Error
if (error.response.status == 401){
Plots_sitop.getToken().then(response => {
token = response.data.access_token
localStorage.setItem('token', token)
this.getResposta()
})
}
})
},
// Função utilizada quando os dados estão mockados
search: function(){
this.$refs.search.style.height = "auto";
var searchText = this.searchText;
var result = false;
this.vetRespostas = []
for(var i in this.quests[0]){
if(searchText == this.quests[0][i][0].pergunta){
result = true;
this.vetRespostas = this.quests[0][i][0].resposta;
console.log(this.vetRespostas)
}
}
if(result == false){
console.log('deu erro')
// this.$refs.erro.style.display = "inline";
}
}
}
})
</script>
<style>
#layout{
flex-direction: row;
}
#search{
height: 80vh;
display: flex;
flex-direction: column;
justify-content: center;
}
#card, #plot_1, #erro, #plot_2, #plot_3{
display: none;
}
</style>
这是我的组成部分:
<template>
<v-flex>
<v-card id = "plot" class="d-flex align-center" light height="400"></v-card>
</v-flex>
</template>
<script>
import Plotly from 'plotly.js'
export default {
data(){
return{
data: [{
x: false,
y: false,
type: false
}],
layout: {
title: false,
xaxis:{
title: false,
showgrind: false,
zeroline: false
},
yaxis: {
title: false,
zeroline: false
}
},
}
},
props: ['dataProps', 'layoutProps'],
mounted (){
this.data = this.dataProps
this.layout = this.layoutProps
Plotly.newPlot('plot',this.data,this.layout)
}
}
</script>
<style>
</style>
和
<template>
<v-flex>
<v-card class="mx-auto" dark v-model='text' color="rgb(0,140,69)" height="400">
<v-card-text class="display-2 text-xs-center font-weight-black"> {{text}}</v-card-text>
</v-card>
</v-flex>
</template>
<script>
export default {
data(){
return {
text: ''
}
},
props: ['textProps'],
mounted(){
this.text = this.textProps
}
}
</script>
<style>
</style>
我尝试在我的组件上这样做:
mounted (){
this.$nextTick(() => {
this.data = this.dataProps
this.layout = this.layoutProps
Plotly.newPlot('plot',this.data,this.layout) });
}
但是没有用。
我在我的 id 上使用 V-bind 解决了这个问题。
感谢@skirtle 的帮助。