No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Actualizando nuestro index.html para agregar la nueva funcionalidad de routing

12/13
Recursos

Aportes 38

Preguntas 8

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

Me gustaria que fuera mas practico, ir estructurando en orden el codigo y explicar que se hace en cada seccion.
Por ejemplo: con esta funcion guardamos el path de la url actual y en ese momento hacer una prueba imprimiendo la ruta por consola.

Ten铆a un problema, se me generaba el error 鈥淯ncaught TypeError: Cannot read property 鈥榯emplate鈥 of undefined鈥. Esto se generaba porque se cargaba la ruta 鈥渓ocalhost:8000/index.html鈥, la cual no estaba en nuestro archivo routes.js, entonces hay 2 maneras de solucionarlo, o agregas esa ruta a routes.js o simplemente borras el 鈥渋ndex.html鈥 de la url y tu p谩gina cargar谩 sin problemas.

Realmente no me funcion贸 como el profe lo hizo. Aqu铆 va mi soluci贸n, espero les sirva:




Me molesta como en las clases de programaci贸n empiezan a escribir c贸digo y hay que seguirlo, se saltan por completo la l贸gica. El m茅todo de Freddy con la tablet donde primero explica TOOOOOODOOOO lo que pasa en el programa y luego empieza a codear es perfecto, no se porque no se lo exigen a todos los profesores, sobre todos los de js鈥ue insisto鈥mpiezan a agregar c贸digo y por alguna raz贸n piensan que los que estamos aprendiendo les podemos seguir el ritmo.

La soluci贸n creo que esta un poco rebuscada, les comparto mi soluci贸n

Path.js

const PATHS = {
    home: {
        path: "/",
        template: "<h1>Home 馃彔</h1>",
    },
    about: {
        path: "/about",
        template: "<h1>Sobre mi 馃懆馃徎鈥嶐煉</h1>",
    },
    contact: {
        path: "/contact",
        template: "<h1>Contacto 馃摬</h1>",
    },
    error: {
        path: "/",
        template: "<h1>Error 鉀旓笍</h1>",
    },
}

Router.js

class Router {
    /**
     * Metodo inicial.
     *
     * @return {void}.
     */
    constructor(paths) {
        this.paths = paths;
        this.initRouter();
    }

    /**
     * Permite inicializar el router
     *
     * @return {void}.
     */
    initRouter() {
        const { location: { pathname = "/" } } = window;
        const URI = pathname === "/" ? "home" : pathname.replace("/", "");
        this.load(URI);
    }

    /**
     * Permite iniciar la carga de paginas.
     *
     * @return {void}.
     */
    load(page = "home") {
        const { paths } = this;
        const { path, template } = paths[page] || paths.error;
        const $CONTAINER = document.querySelector("#content");
        $CONTAINER.innerHTML = template;
        window.history.pushState({ }, "Genial", path);
    }

}

const ROUTER = new Router(PATHS);

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Manejo de Routers</title>
 </head>
<body>
    <header>
        <nav>
            <ul>
                <li>
                    <button id="Home" onclick="ROUTER.load('home')">Home</button>
                </li>
                <li>
                    <button id="About" onclick="ROUTER.load('about')">About</button>
                </li>
                <li>
                    <button id="Contact" onclick="ROUTER.load('contact')">Contact</button>
                </li>
            </ul>
        </nav>
    </header>
    <section>
        <div id="content">
        </div>
    </section>
    <footer></footer>
    <script src="./Paths.js"></script>
    <script src="./Router.js"></script>
</body>
</html>

Con esa explicaci贸n del final me qued贸 m谩s claro lo que est谩bamos haciendo! 馃槃

mi ejemplo de lo aprendido en este curso yo agregue botones con class de **bootstrap **

Yepaaaaa!!! al fin se probara el c贸digo, vaya mas mierda de profe

Hola compa帽eros, me pas贸 que si escribo una ruta que no existe, el programa se rompe, para resolver el error, agregu茅 en la funci贸n _matchUrlToRoute una condici贸n antes del return que devuelve un objeto con solo la propiedad template

if (matchedRoute === undefined) {
	return {
		template: '<h1>Not found</h1>'
	};
}

return matchedRoute;

Me ha gustado mucho el curso y creo que es bastante 煤til: Felicito al profesor por su entusiasmo y la materia aportada pero creo que deber铆a haberlo preparado mejor. Por ejemplo, ir probando resulatdos parciales y no esperar hasta el final para que todo funcione con el 煤ltimo return. Algunas explicaciones tambi茅n dejan algo que desear. Espero que se tome mi comentario como una critica constructiva alejada por supuesto de la intencionalidad de comunuicar una verdad absoluta y de nuevo le doy las gracias al profesor por haberme ayudaddo a aprender. Pero Platzi no es cualquier academia sino la puerta abierta del conocimiento digital a much铆sima gente. Si entre todos conseguimos que sea a煤n mejor de lo que es, nos beneficiaremnos por partida boble o tal vez triple.

Saludos
Vicent

Un gran curso la verdad, me gusta la l贸gica con la que el profesor trabaja y aprend铆 nuevos conceptos de JS. Me funcion贸 todo perfecto, ac谩 les dejo mi c贸digo.
index.html

routes.js

router.js

index.js

He creado mi propia solucion porque no me iba el evento onclick

  <body>
    <header>
      <ul>
        <li>
          <button data-router="">Home</button>
        </li>
        <li>
          <button data-router="portfolio">PorFolio</button>
        </li>
        <li>
          <button data-router="aboutme">About Me</button>
        </li>
        <li>
          <button data-router="contact">Contact</button>
        </li>
      </ul>
    </header>
    <div id="root"></div>
    <script src="./index.js" type="module"></script>
  </body>
const routerOutElm = document.querySelector("#root");
import Router from "./router.js";
import { routes } from "./routes.js";

/* Seleccionamos los botones */
const btnListRoute = [...document.querySelectorAll("[data-router]")];

/* Genero eventos Cliks del menu de navegaci贸n */
btnListRoute.forEach((btn) => {
  btn.addEventListener("click", () => {
    router.loadRoute(btn.dataset.router);
  });
});

/* Declaro la instancia de Router */
const router = new Router(routes);```


Resultado de la ventana Ayuda del curso.

Si les sirve. Me tope con el error 鈥渞outer is not defined鈥, y me encontr茅 con que el error o mi error se estaba en el onclick, que utiliz谩bamos en html.

En lugar de eso lo hice de esta forma.

se olvido de dejar el codigo para poder amalizarlo mejor

Tengo aun este error, ya trate de debuggear pero no encontre como solucionarlo, compa帽eros en esta clase llegaron a tener el mismo problema, uso VS con Live Server

router.js:14 Uncaught TypeError: Cannot read property 'template' of undefined
    at Route.loadRoute (router.js:14)
    at Route._loadInitialRoute (router.js:36)
    at new Route (router.js:4)
    at index.js:1
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Curso/Taller SPA</title>
</head>

<body>
    <header>
        <ul>
            <li><Button onclick="router.loadRoute('')">Home</Button></li>
            <li><Button onclick="router.loadRoute('contact')">Contacto</Button></li>
            <li><Button onclick="router.loadRoute('about')">Acerca de mi</Button></li>
        </ul>
    </header>
    <div data-router>
        <!-- Builder -->
    </div>
    <script src="router.js"></script>
    <script src="routes.js"></script>
    <script src="index.js"></script>
</body>

</html>
const routes = [
    {
        path: '/',
        template: '<h1>Hola</h1>'
    },
    {
        path: '/contact',
        template: '<h1>Contacto</h1>'
    },
    {
        path: '/about',
        template: '<h1>Acerca de mi</h1>'
    },
    {
        path: '/index.html',
        template: '<h1>Home</h1>'
    }
];
class Route {
    constructor(routes) {
        this.routes = routes;
        this._loadInitialRoute();
    }

    loadRoute(...urlSegs) {
        const matchedRoute = this._matchUrlToRoute(urlSegs);
        // debugger
        const url = `/${urlSegs.join('/')}`;
        history.pushState({}, 'This works', url);
        // debugger
        const routerOutElm = document.querySelectorAll('[data-router]')[0];
        routerOutElm.innerHTML = matchedRoute.template;
    }

    _matchUrlToRoute(urlSegs) {
        const matchedRoute = this.routes.find(route => {
            const routePathSegs = route.path.split('/').slice(0);
            // debugger
            if (routePathSegs.length !== urlSegs.length) {
                // debugger
                return false;
            }
            // debugger
            return routePathSegs
                .every((routePathSeg, i) => routePathSeg === urlSegs[i])
        });

        if (matchedRoute === undefined) {
            return {
                template: '<h1>Not found</h1>'
            };
        }

        return matchedRoute;
    }

    _loadInitialRoute() {
        const pathNameSplit = window.location.pathname.split('/');
        const pathSegs = pathNameSplit.length > 1 ? pathNameSplit.slice(1) : '';

        this.loadRoute(...pathSegs)
    }
}
const router = new Route(routes);

Trate de arreglarlo con una validacion sugerida, sin embargo NO funciona

Una peque帽a acotaci贸n para MEJORAR el rendimiento en su c贸digo. En el condicional donde se comparan los arrays, hay un peque帽o error:

const matchedRoute = this.routes.find( (route) => {
            const  routePathSegs = route.path.split("/").slice(1)

	    // ESTE
            if(routePathSegs.length !== urlSegs.length){
                return false
            } 

            return routePathSegs
                .every((routePathSeg, i) => routePathSeg === urlSegs[i])
        })

Ac谩 lo que se explic贸 es que se querian comparar los strings de ambos arrays, tanto de routePathSegs
como urlSegs, pero si debuggean su c贸digo y ven lo que hace paso a paso, se dar谩n cuenta que nunca entra al condicional porque as铆 como estaroutePathSegs.length !== urlSegs.length Lo que hace es comparar el tama帽o del array en s铆 y por como han sido trabajados con los m茅todos slice() y split() siempre tendran un length de 1, as铆 que esa comparaci贸n no funciona.

Entonces, porque si funciona el c贸digo en general? por el metodo every(), donde se comparan que si sean iguales.
.

Optimizaci贸n

Para optimizar el c贸digo y entre al if cuando sean de tama帽os distintos solo hace falta agregar:

 if(routePathSegs[0].length !== urlSegs[0].length){
                return false
            }

Como les dije, siempre es un array de un elemento as铆 que su 铆ndice siempre ser谩 0. Con este cambio los valores diferentes entraran al condicional, retornaran false y permitir谩n la siguiente iteraci贸n, sin necesidad de pasar por el every()

Hola todos, espero est茅n bien, yo al momento de ejecutar el c贸digo tengo este error, alguien que me de una mano, se los agradecer铆a mucho.

Para sacarle provecho a este codigo habira que crear templates en archivos externos y pasarlos en vez de escribir el template directamente en el archivo routes.js

Despues de seguir todo el curso, no me funciona. He repasado el codigo de los archivos y en consola tengo este error:

router.js:13 Uncaught TypeError: Cannot read property 'template' of undefined at Router.loadRoute (router.js:13) at Router._loadInitialRoute (router.js:36) at new Router (router.js:4) at index.js:1

Lo modifique para que tenga un template de error404 si no exite la pagina dentro de los array de routes. aqui

Este es mi aporte, corrige lo que no funcionaba y le agregue not found en caso de que la ruta no este disponible.

class Router {

    constructor (routes) {
        this.routes = routes;
        //Para cargar ruta inicial del proyecto
        this._loadInitialRoutes();
    }
    
    loadRoutes(...urlSegs){
        const matchedRoute = this._matchUrlToRoute(urlSegs);
        const url = `/${urlSegs.join('/')}`;
        window.history.pushState({},'this word',url);
        const routerOutElem = document.querySelectorAll(['#data-router'])[0];
        routerOutElem.innerHTML = matchedRoute.template;
    }

    _matchUrlToRoute(urlSegs){
        const notFound = this.urlNotFound();
        const matchedRoute = this.routes.find ( route => {
        const routePathSeges = route.path.split('/').slice(1);
            if (routePathSeges === ''){
                return '/'
            }else if (routePathSeges[0] === urlSegs[0] ){
                return route;
            }
        })
        // En caso de no encontrar la ruta retorna 404
        const urlMatch = matchedRoute !== undefined ? matchedRoute : notFound
        return urlMatch;
    }

    // Busco el path 404 
    urlNotFound() {
        const notFound = this.routes.find(route => {
            return route.path ==='/404';
        })

        return notFound;
    }


    _loadInitialRoutes(){
        const pathNameSplit = window.location.pathname.split('/');
        const pathSegs = pathNameSplit.length > 1 ? pathNameSplit.slice(1) : '';
        this.loadRoutes(...pathSegs);
    }
}

Es mejor modularizar los scripts, as铆 s贸lo llamas uno.

KeMonito!

Si tienen una ruta como /user/andrea/picture2 tienen que pasarle un array a router.loadRoute(), en este ejemplo ser铆a router.loadRoute([鈥榰ser鈥, 鈥榓ndrea鈥, 鈥榩icture2鈥橾)

tengo el siguiente error:
Uncaught ReferenceError: routes is not defined
at index.js:1
revise el c贸digo pero no encuentro lo malo

index

const router =  new Router(routes);

routes

const route = [
    {
        path: '/',
        template: '<h1>Hola</h1>'
    },
    {
        path: '/contacto',
        template: '<h1>contacto</h1>'
    },
    {
        path: '/aboutme',
        template: '<h1>About me</h1>'
    }
];


router

class Router{

    constructor(routes) {
        this.routes= routes;
        this._loadInitialRoute();
    }

    loadRoute(...urlSegs){
        const matchedRoute = this._matchUrlToRoute(urlSegs);

        const url = `/${urlSegs.join('/')}`;
        history.pushState({},'this works', url);

        const routerOutElm = document.querySelectorAll('[data-router]')[0];
        routerOutElm.innerHTML = matchedRoute.template;
    }

    _matchUrlToRoute(urlSegs) {
        const matchedRoute = this.routes.find(route =>{
            const routePathSegs = route.path.split('/').slice(1)

            if (routePathSegs.lenght !== urlSegs.leng){
                return false;
            }

            return routePathSegs
            .every((routePathSeg, i) => routePathSeg === urlSegs[i]);
            
        });

return matchedRoute;

    }

    _loadInitialRoute() {

        const pathNameSplit =window.location.pathname.split('/');
        const pathSegs = pathNameSplit.length > 1 ? pathNameSplit.slice(1): '';
        
        this.loadRoute(...pathSegs);
    }
}

su ayuda 馃槖

No funca 馃槍

Hola, me sale el error Uncaught TypeError: matchedRoute is undefined. Ya estoy cansado de leer el c贸digo. alguien tuvo este problema?

alguien me puede explicar esta l铆nea ?
no entiendo porque el objeto vac铆o y el mensaje

history.pushState({}, 'this works', url)

Hola!

  • Primero si tuvieron errores a la hora de cargar rutas espec铆ficas, puede ser porque est谩n usando Live-server, en es caso deben de usar el servidor propuesto por el Ricardo! 馃槑

  • Segundo yo realic茅 una implementaci贸n simplificando un poco m谩s todo, los invito a que la miren en el Repositorio

Y les comparto el c贸digo del Router

y el Index

As铆 qued贸

驴al colocar en los scripts src=鈥欌/鈥 no saldr铆a del entorno de desarrollo donde se encuentra trabajando?, si no me equivoco hay un error all铆.

Demasiados errores en el c贸digo, deber铆an de pasar un filtro m铆nimo antes de poder subir el curso. Aqu铆 el c贸digo que me funciono usando Live Server

index.html

<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cliente de nuestro SPA Router</title>
</head>

<body>
    <header>
        <ul>
            <li><button onclick="router._loadRoute('index.html')">Home</button></li>
            <li><button onclick="router._loadRoute('contacto')">Contacto</button></li>
            <li><button onclick="router._loadRoute('aboutme')">About me</button></li>
        </ul>
    </header>
    <div data-router>
    </div>
    <script src="/router.js"></script>
    <script src="/routes.js"></script>
    <script src="/index.js"></script>
</body>

</html>

routes.js

const routes = [{
        path: '/index.html',
        template: '<h1> Hola </h1>'
    },
    {
        path: '/contacto',
        template: '<h1> Contacto </h1>'
    },
    {
        path: '/aboutme',
        template: '<h1> About Me </h1>'
    },
];

router.js

class Router {
    constructor(routes) {
        this.routes = routes;
        this._loadInitialRoute();
    }

    _loadRoute(...urlSegs) {
        const matchedRoute = this._matchUrlToRoute(urlSegs);
        const url = `/${urlSegs.join('/')}`;
        history.pushState({}, 'this works', url);
        const routerOutElm = document.querySelectorAll('[data-router]')[0];
        routerOutElm.innerHTML = matchedRoute.template;
    }

    _matchUrlToRoute(urlSegs) {
        const matchedRoute = this.routes.find(route => {
            const routePathSegs = route.path.split('/').slice(1);
            if (routePathSegs.length !== urlSegs.length) {
                return false;
            }
            return routePathSegs.every((routePathSegs, i) => routePathSegs === urlSegs[i])
        });
        return matchedRoute;
    }

    _loadInitialRoute() {
        const pathNameSplit = window.location.pathname.split('/');
        const pathSegs = pathNameSplit.length > 1 ? pathNameSplit.slice(1) : '';
        this._loadRoute(...pathSegs);
    }
}

index.js

const router = new Router(routes);

Con el error, que soluciono Ricador en el minuto 3:20, me ha funcionado. aqu铆 mi implementaci贸n.

Index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Router</title>
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@100;300;600&display=swap" rel="stylesheet">
    <style>
        body, * {
            margin:0px;
            padding: 0px;
        }

        body{
            background: rgb(254,254,254);
            background: radial-gradient(circle, rgba(254,254,254,1) 0%, rgba(227,225,225,1) 35%, rgba(228,228,228,1) 100%);
            font-family: 'Montserrat', sans-serif;
            position: relative;
        }

        header{
            width: 100vw;
            height: 80px;
            background-color: #fed049;
        }

        header ul {
            display: flex;
            flex-wrap: nowrap;
            justify-content: space-evenly;
            list-style: none;
            height: 100%;
            align-items: center;
        }

        header ul li span{
            font-size: 24px;
            cursor: pointer;
        }

        section{
            width: 100%;
            position: relative;
        }

        section .wrapper{
            width: 80%;
            margin: 0 auto;
            text-align: center;
            position: relative;
            padding: 5% 10%;
        }

        section .wrapper h1{
            font-size: 40px;
        }

        section .wrapper p{
            margin: 35px 10px 15px;
            padding: 0px 15px;
        }
    </style>
</head>
<body>
    <header>
        <ul>
            <li class="home"><span>Home</span></li>
            <li class="aboutus"><span>About Us</span></li>
            <li class="contactus"><span>Contact Us</span></li>
        </ul>
    </header>

    <section>
        <div class="wrapper">
            <h1> Welcome goide :) </h1>
            <h2> Make a Router with JavaScript Vanilla.</h2>
            <p>
                Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed justo in metus imperdiet interdum. Aliquam vestibulum in est vitae semper. In ornare rhoncus mi, a malesuada enim eleifend ac. Duis non elit eros. Maecenas fringilla semper lorem, et interdum nibh blandit sit amet. Ut quam nisi, elementum eget maximus a, pretium hendrerit quam. Integer congue congue turpis eget suscipit. Sed a sollicitudin est, malesuada varius erat. Aliquam tincidunt nisl id nibh placerat, auctor auctor odio tincidunt. Proin commodo aliquam libero mollis lacinia.
            </p>
        </div>
    </section>

    <script src="/src/router.js"></script>
    <script src="/src/routes.js"></script>
    <script src="/src/index.js"></script>

</body>
</html>

Routes.js

const routes = [
    {
        path: '/',
        template: `Welcome goide :)`
    },
    {
        path: '/about-us',
        template: `About Us`
    },
    {
        path: '/contact-us',
        template: `Contact Us`
    }
];

Router.js

class Router{
    constructor(routes){
        this.routes = routes;
        this._loadInitialRoutes(); 
    }

    loadRoute(...urlSegs){
        const matchedRoute = this._matchUrlToRoute(urlSegs);

        const url = `/${urlSegs.join('/')}`;
        window.history.pushState({}, 'this works', url);

        const routerOutElm = document.querySelector('h1');
        routerOutElm.innerHTML = matchedRoute.template;
    }

    _matchUrlToRoute(urlSegs){
        const matchedRoute = this.routes.find( route => {
            const routePathSegs = route.path.split('/').slice(1);

            if(routePathSegs.length !== urlSegs.length){
                return false;
            }

            // El emtodo every nos permite, Determina si todos los elementos en el array satisfacen una condici贸n.
            // o sea verifica cada elemento del array que todos sean true, en este caso es una letra, las verifica letra por letra
            return routePathSegs.every((routePathSeg, i) => routePathSeg === urlSegs[i]);
        });

        return matchedRoute;
    }

    _loadInitialRoutes(){
        // vamos a usar el metodo split, El m茅todo split() divide un objeto de tipo String en un array (vector) de cadenas mediante la separaci贸n de la cadena en subcadenas.
        // en este caso: split('/') -> nos separa todo lo de la parte derecha luego del slash de la url
        const pathNameSplit = window.location.pathname.split('/');
        // Segmentar nuestro path
        // el metdo slice, devuelve una copia de una parte del array dentro de un nuevo array empezando por inicio hasta fin (fin no incluido).
        const pathSegs = (pathNameSplit.length > 1) ? pathNameSplit.slice(1) : '';

        this.loadRoute(...pathSegs);
    }

}

Index.js

const router = new Router(routes);

const pathHome = () => {
    console.log('Home')
    router.loadRoute('');
}

const pathAbout = () => {
    console.log('About - Us ')
    router.loadRoute('about-us');
}

const pathContact = () => {
    console.log('Contact - Us ')
    router.loadRoute('contact-us');
}

const home = document.querySelector('.home');
home.addEventListener('click', pathHome);

const about = document.querySelector('.aboutus');
about.addEventListener('click', pathAbout);

const contact = document.querySelector('.contactus');
contact.addEventListener('click', pathContact)

Podemos agregar una pagina 404 si en el return de _matchUrlToRoute agregamos esto

    return matchedRoute ? matchedRoute : this.routes[this.routes.length - 1]

y en la parte de routes agregamos al final un template de 404

Buenas tardes chicos , implemente la soluci贸n de colocar en la ruta index.html, y me carga perfectamente juntamente con los templates de contacto y about... pero cuando me coloco en una de estas dos 煤ltimas me aparece el error cannot GET contacto/ y tambi茅n en cannot GET /about... el codigo est谩 igual al del profesor a excepci贸n de ms modificaci贸n que describ铆 al principio alguno pudo solucionar??? necesito ayuda 馃槦馃槦馃槦馃槦馃槦馃槦

platzi terminaran siendo un libro digital, te dan toda la info, pero nuevamente vuelves tu a tener que estudiar todo hasta que lo entiendas, por lo menos los creadores de contenido de youtube, se toman hasta 2 -3 horas explicando las funcionalidades de las cosas, aca nuevamente graban lo que leen de otra pantalla y listo, curso terminado, estudien ahora si.

f

Les comparto mis apuntes de todo el curso por si se pierden en alg煤n momento: https://app.gitbook.com/@afgallegoz/s/creacion-de-router-spa/