Solucionado (ver solução)
Solucionado
(ver solução)
17
respostas

Redirecionamento fora de um componente

import Vue from 'vue'
import VueResource from 'vue-resource'
import VueRouter from 'vue-router'

export default {
    ExitUser () {
    // tentei todos esses
    this.$router.router.go('login');
    this.$router.router.go('/login');
    this.$router.push('/login');
    this.$router.push('login');
    this.$router.push({ path: 'login' });
    Vue.router.push({ path: 'login' });
    Vue.$router.push({ path: 'login' });
    Vue.this.$router.push({ path: 'login' });
    }
}

Alguém já fez algo parecido e pode ajudar ?

Desde já obrigado.

17 respostas

Bom, eu não entendi bem o que você está fazendo. Mas a maneira que você está utilizando é a maneira que é feito DENTRO do componente.

Para fazer redirecionamentos fora do componente, dentro do arquivo Router, você pode usar a variável que você importou. No seu caso fica o seguinte

VueRouter.push({name: 'login'}) // "name" se você declarou essa propriedade no VueRouter ela estará disponível

Você usa a chamada this.$router só se você estiver "puxando" o router dentro da tag <script> do seu componente

No meu git, nessa file abaixo, tem um exemplo de como eu fiz no meu.

O cenário é o seguinte gostaria de deixa isolado em um arquivo JS a responsabilidade de expulsar um usuário do sistema, e essa função faz sentido também ser executada no click do botão sair do sistema

 import Vue from 'vue'
 import VueResource from 'vue-resource'
 import VueRouter from 'vue-router'
 import router from '../../routes/routes'

export default {

    ExitUser () {
        VueRouter.push({name: 'login'});
    }
}

aparece o seguinte erro _vueRouter2.default.push is not a function

Eu fiz isso na minha App. Mas você vai expulsar ele quando ele tentar acessar uma URL protegida ou quando ele der logout?

Para ambos, você importa a variável do Router dentro do arquivo final. Você não vai usar Export default também. Você faz o seguinte pra isso funcionar. No arquivo que você vai executar o logout do usuário:

export function ExitUser () {
        VueRouter.push({name: 'login'});
    }
}

E ao importar no index do router, vamos supor que você queira redirecionar ele quando ele não estiver logado para ele logar novamente. Você vai usar o Router Guards

import VueRouter from 'vue-router'
import { ExitUser } from '@/utils/auth' //aqui você importa apenas a função que precisa de lá do documento

{
      path: '/',
      name: 'dashboard',
      component: Dashboard,
      beforeEnter: ExitUser, <-- você usa o beforeEnter pra pegar o usuário antes de ele entrar na rota e pode redirecionar ele. Você teria que fazer verificação de login dele, mas aí é pela sua lógica mesmo
}

Aqui um pouco mais sobre o Navigation Guards

Se ainda não funcionar, madna o código todo ou o Github pra gente ver aonde que está ocorrendo o erro

César, deu certo ai ?

Allan agradeço muito pela sua ajuda, mais não consegui fazer funcionar dessa forma que me mostrou.

ha dois momentos em que devo enviar o user para tela de login, uma é quando ele clica em sair, e outra quando o interceptor identifica que o user não esta mais com o TOKEN valido.

gostaria de deixar em um método ou class essa responsabilidade, ai chamaria-o todo vez que precisar expulsar um user do sistema.

vou tentar seguir seu exemplo do git, mais só vou trabalhar nesse projeto no final de semana agora.

Muito obrigado pela ajuda.

Sem problemas. Se possível, manda o código no seu git e eu te ajudo a resolver no final de semana

Allan segue o codigo meu no git

https://github.com/FelipeFalanque/Vue-Teste-Login

esse momenta esta funcionando mais não do jeito que eu quero.

o codigo esta bem simples e comentado, facil de enterder

o código é o cenário mais próximo possível do meu código de produção

<script>
import SegurancaService from '../../domain/seguranca/SegurancaService'
export default {
  data() {
    return {
      contador: 0,
      serice: new SegurancaService()
    };
  },
  methods: {
    sair(){
      this.serice.ExitUser(this.$router);
      //assim funciona
      //this.$router.push({ name: 'login' });
    },
    verifica(){
      this.contador++;
      if (this.contador >= 5){
        // devo expulsar o user de dentro do sistema
        //this.$router.push({ name: 'login' });
        this.serice.ExitUser(this.$router);
      }
    }
  },
};
</script>

mas o que eu desejo e não passar o router de parâmetro, porque esse método ExitUser pode ser chamado de uma classe javascript e não de um componente e nessa classe não tenho o this.$router

Você não vai acreditar, mas ai vai.

Eu entrei no sistema, abri. Loguei com usuário e senha ficticio e na hora que o contador deu 5, ele me redirecionou para a tela de login.

Parece que ele funcionou então.

Se isso era o que você estava esperando, o que deve estar acontecendo com você são dependências desatualizadas ou o próprio VueJS.

Tenta atualizar o Vue e as dependências do seu projeto e tenta de novo

esse código esta funcionando, foi o jeito que consegui fazer ele funcionar, porem o que eu quero fazer é que o metodo ExitUser(this.$router) não receba parâmetro, pois pode ser que eu o chame dentro de outra classe ou função javascript, e nesse momento eu não tenha acesso a this.$router

import Vue from 'vue'
import VueRouter from 'vue-router'

export default class SegurancaService {
    // Construtor da Classe
    constructor(){
        console.log('Entro no construtor da class SegurancaService');
    };
    // Chamo para expulsar user
    // Assim funciona porem no meu codigo de produção não tenho certeza que vou semtre chamar
    // esse metodo dentro de um componente aonde tenho um this.$router
    ExitUser (router) {
        router.push({ name: 'login' });
    };
}

então preciso de algo assim , sem passar parametro

import Vue from 'vue'
import VueRouter from 'vue-router'

export default class SegurancaService {
    // Construtor da Classe
    constructor(){
        console.log('Entro no construtor da class SegurancaService');
    };
    // Chamo para expulsar user
    // Sem passar parametro 
    ExitUser () {
        VueRouter.router.push({ name: 'login' });
    };
}

porem desse jeito que eu preciso não consegui fazer ainda.

Deixa eu ver se entendi.

Você quer receber uma url pra fazer o ExitUser na hora que o usuário for deslogado? Se for isso, o VueRouter disponibiliza todos os endereços na função this.$router.options.routes e você pode guardar o array com eles no VueX sem problemas

Ou você quer apenas garantir que o router sempre vai estar disponível? Nesse caso, ele declarado dentro do documento da classe, vai sempre estar disponível dentro deste documento, não necessitando de você chamar ele dentro do componente.

supondo que ele esteja desse jeito:

import Vue from 'vue'
import VueRouter from 'vue-router'

export default class SegurancaService {
    // Construtor da Classe
    constructor(){
        console.log('Entro no construtor da class SegurancaService');
    };
    // Chamo para expulsar user
    // Sem passar parametro 
    ExitUser () {
        VueRouter.router.push({ name: 'login' });
    };
}

E você tenha este código, que é o que está no seu github, mas sem o parâmetro no exitUser:

<script>
import SegurancaService from '../../domain/seguranca/SegurancaService'
export default {
  data() {
    return {
      contador: 0,
      serice: new SegurancaService()
    };
  },
  methods: {
    sair(){
      this.serice.ExitUser();
      //assim funciona
      //this.$router.push({ name: 'login' });
    },
    verifica(){
      this.contador++;
      if (this.contador >= 5){
        // devo expulsar o user de dentro do sistema
        //this.$router.push({ name: 'login' });
        this.serice.ExitUser(this.$router);
      }
    }
  },
};
</script>

Ele vai funcionar ( testado )

Por que na prática, o que o VueJS está fazendo por debaixo dos panos é isso aqui

import Vue from 'vue'
import VueRouter from 'vue-router'

export default class SegurancaService {
    // Construtor da Classe
    constructor(){
        console.log('Entro no construtor da class SegurancaService');
    };
    // Chamo para expulsar user
    // Sem passar parametro 
    ExitUser () {
        VueRouter.router.push({ name: 'login' });
    };
} 


export default {
  data() {
    return {
      contador: 0,
      serice: new SegurancaService()
    };
  },
  methods: {
    sair(){
      this.serice.ExitUser();
      //assim funciona
      //this.$router.push({ name: 'login' });
    },
    verifica(){
      this.contador++;
      if (this.contador >= 5){
        // devo expulsar o user de dentro do sistema
        //this.$router.push({ name: 'login' });
        this.serice.ExitUser();
      }
    }
  },
};

Então você não passa parâmetro pro ExitUser por que você já está importando ele dentro do SegurancaService.

Quando você importar o Segurança Service, ele vai chamar junto todos os requires que você fez dentro dele e funcionar normalmente

Eu não sei se consegui ser claro, se não consegui, me dá um toque

Allan atualizei o código no git, o que eu quero fazer talvez seja a segunda opção que falou

quero que o vue-router sempre esteja disponível, sendo assim não preciso passar o router, importo ele própria classe então só chamaria o metodo

this.serice.ExitUser();

onde eu preciso depois de instanciado a classe SegurancaService, e então o user é expulso.

alterei o código mais ainda não funcionou, pode atualizar o código e ver se funciona ai ? pois aqui não funcionou. da o erro Cannot read property 'push' of undefined

Vou dar uma olhada daqui umas duas horas, ok?

Agora eu to resolvendo um probleminha com um script de MongoDB / Node aqui no trabalho

:)

Meu querido, acho que encontrei uma solução pro seu problema, mas vai exigir um pouco de refatoração. Vou escrever a solução aqui agora

Seguinte, o Vue trabalha com forte encapsulamento de componentes.

Primeiramente, isso evita que você acidentalmente chame um evento ou variável aonde você não quer chamar. Também mantém os componentes perfeitamente isolados um dos outros. Com o vue-router não é diferente. Ele encapsula o VueRouter pra que ele não fique disponível globalmente e, ao você usar algum método, ele não acabe disparando por debaixo dos panos.

Seguinte: Para fazer o que você quer funcionar, temos que fazer do VueRouter um componente global. A maneira que encontrei de fazer isso foi colocando o router na definição de Vue. Assim, o Router fica disponível quando eu chamar Vue.router.

Altere seu main.js para o seguinte:

import Vue from 'vue'
import App from './App.vue'
import VueResource from 'vue-resource';
import router from './routes';

Vue.use(VueResource);

Vue.router = router

new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

Agora, a gente vai definir o New VueRouter dentro do componente de rotas. Ent'ao no seu arquivo routes.js, você faz o seguinte:

import Login from '../src/components/login/Login.vue';
import Home from '../src/components/home/Home.vue';
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)


const router = new VueRouter({

    routes: [    
        { path: '/', component: Login, redirect: '/login' },
        { path: '/home',  name: 'home', component : Home, titulo : 'Home' },
        { path: '/login',  name: 'login', component : Login, titulo : 'Login' }
    ]
});

export default router;

O que fazemos aqui é exportar o router como default para a definição das rotas como um todo ficar disponível

Agora dentro do SegurancaService.js

import Vue from 'vue'
import VueRouter from 'vue-router'

export default class SegurancaService {
    // Construtor da Classe
    constructor(VueRouter){
        console.log('Entro no construtor da class SegurancaService');
    };
    // Chamo para expulsar user
    // Assim funciona porem no meu codigo de produção não tenho certeza que vou semtre chamar
    // esse metodo dentro de um componente aonde tenho um this.$router
    /*ExitUser (router) {
        router.push({ name: 'login' });
    };*/
    ExitUser () {

        Vue.router.push({ name: 'login' });
    };
}

Voce consegue chamar o Vue.router sem passar nenhum parâmetro

Então, no seu arquivo Home.vue você pode usar assim:

<script>
import SegurancaService from '../../domain/seguranca/SegurancaService'
export default {
  data() {
    return {
      contador: 0,
      serice: new SegurancaService()
    };
  },
  methods: {
    sair(){
      //this.serice.ExitUser(this.$router);
      //assim funciona
      //this.$router.push({ name: 'login' });
      this.serice.ExitUser();
    },
    verifica(){
      this.contador++;
      if (this.contador >= 5){

        // devo expulsar o user de dentro do sistema
        // this.$router.push({ name: 'login' });
        this.serice.ExitUser();
        // this.serice.ExitUser();

      }
    }
  },
};
</script>
solução!

Devo lembrar, entretanto, que é perfeitamente possível você também passar uma variável na instanciação da classe e usar ele dentro da classe, essa maneira, você disponibiliza o VueRouter dentro da classe, mas chama apenas na instancia dele.

return {
      contador: 0,
      serice: new SegurancaService(this.$router)
    };

E no seu construtor, você pode ficar ouvindo a entrada dele:

export default class SegurancaService {
    // Construtor da Classe
    constructor(VueRouter){
        console.log('Entro no construtor da class SegurancaService');

        this.router = VueRouter

    };
}

Essa maneira é mais limpa e você não precisa deixar o VueRouter "solto" no meio do seu programa, deixa ele com melhor manutenabilidade e de quebra segue padrões bem estabelecidos de programação

:)

Espero que isso ajude

Allan muito obrigado pela sua dedicação em me ajudar.

Precisando é só chamar!

Mexo muito com o Vue.js. Procura a comunidade do Vue no Telegram e entra pra lá. Procura também ler bastante a documentação e aprender também sobre o VueX

Qualquer coisa é só gritar!