PIXEL FACEBOOK

Cree rápidamente SPA complejos con vue-element-admin

Cree rápidamente SPA complejos con vue-element-admin

La arquitectura de aplicaciones de una sola página (SPA) ha sido una de las tendencias más importantes en el desarrollo web desde hace bastante tiempo. Como desarrolladores, los marcos de JavaScript como Angular, React, Svelte y Vue.js le permiten generar un SPA mediante una interfaz de línea de comandos (CLI). Algunos casos en los que puede necesitar un SPA incluyen:

  • Cuando crea una aplicación de comercio electrónico como Jumia o un servicio de transmisión de películas como Netflix
  • En términos más generales, cuando crea un panel de administración

Los paneles de administración son complejos ya que manejan consultas de red, gráficos, comunicación en tiempo real, tablas de datos, componentes de interfaz de usuario, etc. Debido a su complejidad, los equipos de desarrolladores tienden a comprar plantillas prefabricadas y personalizarlas.

Pero si es un desarrollador front-end que trabaja principalmente con Vue.js, vue-element-admin es una de las mejores plantillas de administración de Vue gratuitas y de código abierto disponibles. En este artículo, aprenderemos a usar vue-element-admin y exploraremos algunas de sus características.

Saltar hacia adelante:

¿Qué es vue-element-admin?

vue-element-admin es el predecesor de vue-admin-template. Esta es una solución de front-end lista para producción para interfaces de administración que utiliza el kit de herramientas element-ui. Esta plantilla tiene muchas características complejas que puede usar para tableros de nivel empresarial.

Exploremos algunas de las características principales de este proyecto.

Autenticación

Un panel de administración debe tener una función de inicio de sesión para verificar a un usuario. En vue-admin-template, la acción de inicio de sesión enviará los detalles del usuario (nombre de usuario y contraseña) al servidor, y el servidor devolverá un token, que se almacenará en una cookie:

login({ commit }, userInfo) {
    const { username, password } = userInfo
    return new Promise((resolve, reject) => {
      login({ username: username.trim(), password: password }).then(response => {
        const { data } = response
        commit('SET_TOKEN', data.token)
        setToken(data.token)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

Autorización

Otra característica importante de un panel de administración es la definición de roles y permisos de usuario. En este modelo, el rol de usuario se obtiene del token devuelto por el servidor. El rol del usuario determina a qué ruta puede acceder. Esto se calcula dinámicamente:

const hasToken = getToken()

  if (hasToken) {
    if (to.path === '/login') {
      next({ path: "https://blog.logrocket.com/" })
      NProgress.done() 
    } else {
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
      if (hasRoles) {
        next()
      } else {
        try {
          const { roles } = await store.dispatch('user/getInfo')
          const accessRoutes = await store.dispatch('permission/generateRoutes', roles)

          router.addRoutes(accessRoutes)

          next({ ...to, replace: true })
        } catch (error) {
          await store.dispatch('user/resetToken')
          Message.error(error || 'Has Error')
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    }
  } else {
    /* has no token*/
    if (whiteList.indexOf(to.path) !== -1) {      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      next(`/login?redirect=${to.path}`)
      NProgress.done()
    }
  }
})

El fragmento de código anterior muestra cómo se implementan los permisos a nivel de página en esta plantilla. Los usuarios con diferentes permisos verán diferentes barras laterales y solo podrán ingresar a un número limitado de páginas. Es posible que prefiera personalizar esto si su tabla de rutas se genera dinámicamente en el backend.

Componentes de la interfaz de usuario

Como se mencionó anteriormente, vue-element-admin utiliza el kit de herramientas de interfaz de usuario element-ui. Los paneles de administración requieren muchos componentes reutilizables y esta plantilla proporciona más de 25 componentes de interfaz de usuario, incluidos DragSelect, ErrorDialog, MarkdownEditor, Pagination, Charts, etc.

Componente de diseño

Uno de los primeros componentes o vistas que implementará al crear un tablero es el componente Diseño. vue-element-admin consta de:

  • una barra lateral
  • Una barra de navegación
  • EtiquetasVer
  • Contenido

El diseño de una página se define en la configuración del enrutador:

{
    path: '/401',
    component: () => import('@/views/error-page/401'),
    hidden: true
  },
  {
    path: "https://blog.logrocket.com/",
    component: Layout,
    redirect: '/dashboard',
    children: [
      {
        path: 'dashboard',
        component: () => import('@/views/dashboard/index'),
        name: 'Dashboard',
        meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
      }
    ]
  },

Esta configuración facilita la personalización de la barra lateral para que coincida con el rol del usuario.

Solicitudes de red

Los paneles de administración consumen una gran cantidad de puntos finales de API de back-end, por lo que es importante tener un flujo organizado. vue-element-admin maneja esto de manera muy clara y concisa, así que vamos a desglosarlo.

Primero, tenemos una utilidad de consulta que envuelve axios. request maneja todos los POST, GET y otros parámetros de solicitud; solicitar encabezados; y mensajes de error. Las solicitudes de API son módulos en src/api; una consulta típica se ve así:

export function getInfo(token) {
  return request({
    url: '/vue-element-admin/user/info',
    method: 'get',
    params: { token }
  })
}

A continuación, el módulo de red se importa a las acciones de vue-store, así:

import { getInfo } from '@/api/user'

getInfo({ commit, state }) {
    return new Promise((resolve, reject) => {
      getInfo(state.token).then(response => {
        const { data } = response

        if (!data) {
          reject('Verification failed, please Login again.')
        }

        const { roles, name, avatar, introduction } = data

        // roles must be a non-empty array
        if (!roles || roles.length <= 0) {
          reject('getInfo: roles must be a non-null array!')
        }

        commit('SET_ROLES', roles)
        commit('SET_NAME', name)
        commit('SET_AVATAR', avatar)
        commit('SET_INTRODUCTION', introduction)
        resolve(data)
      }).catch(error => {
        reject(error)
      })
    })
  },

Gráficos

Los tableros contienen muchos gráficos para diferentes formularios y datos. Este es otro requisito común. Esta plantilla recomienda Apache ECharts, una biblioteca de visualización JavaScript potente, fácil de usar y flexible.

Personalmente, prefiero esta biblioteca a otras bibliotecas de gráficos debido a su amplia galería, que resulta útil cuando se implementan gráficos para clientes que no están seguros de cómo quieren representar los datos. No profundizaremos en los gráficos electrónicos en este artículo; Puedes ver su documentación aquí.

Construyendo con vue-admin-template

Hasta ahora hemos explorado las funciones de vue-admin-template; Avancemos y mostremos cómo iniciar rápidamente un panel de administración con la plantilla.

condiciones previas

Asegúrese de haber instalado lo siguiente:

Este proyecto también utiliza un servidor simulado, implementado con mockjs. Puede encontrar la implementación simulada en ~/mock.

Después de clonar el repositorio, ejecute npm install para instalar las dependencias del proyecto. Navegue a src/router y edite index.js con este fragmento de código:

//src/router
/* eslint-disable */
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)

import Layout from '@/layout'
export const constantRoutes = [
  {
    path: '/redirect',
    component: Layout,
    hidden: true,
    children: [
      {
        path: '/redirect/:path(.*)',
        component: () => import('@/views/redirect/index')
      }
    ]
  },
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },
  {
    path: '/auth-redirect',
    component: () => import('@/views/login/auth-redirect'),
    hidden: true
  },
  {
    path: '/404',
    component: () => import('@/views/error-page/404'),
    hidden: true
  },
  {
    path: '/401',
    component: () => import('@/views/error-page/401'),
    hidden: true
  },
  {
    path: "https://blog.logrocket.com/",
    component: Layout,
    redirect: '/dashboard',
    children: [
      {
        path: 'dashboard',
        component: () => import('@/views/dashboard/index'),
        name: 'Dashboard',
        meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
      }
    ]
  },
  {
    path: '/posts',
    component: Layout,
    children: [
      {
        path: 'index',
        component: () => import('@/views/posts/index'),
        name: 'Posts',
        meta: { title: 'Posts', icon: 'post', affix: true }
      }
    ]
  },

  {
    path: '/profile',
    component: Layout,
    redirect: '/profile/index',
    hidden: true,
    children: [
      {
        path: 'index',
        component: () => import('@/views/profile/index'),
        name: 'Profile',
        meta: { title: 'Profile', icon: 'user', noCache: true }
      }
    ]
  }
]

/**
 * asyncRoutes
 * the routes that need to be dynamically loaded based on user roles
 */
export const asyncRoutes = [

  // 404 page must be placed at the end !!!
  { path: '*', redirect: '/404', hidden: true }
]

const createRouter = () => new Router({
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  const newRouter = createRouter()
  router.matcher = newRouter.matcher // reset router
}

export default router

Instalación del enrutador Vue

Este proyecto usa Vue Router 3. Aquí tenemos dos tipos de rutas: asyncRoutes y constantRoutes.

Las rutas constantes son globales; cada usuario tiene acceso a estas rutas, mientras que las rutas asincrónicas se cargan dinámicamente según el rol del usuario. Una ruta de administración típica se verá así:

{
    path: '/transactions',
    component: Layout,
    redirect: '/transactions/info',
    alwaysShow: true, // will always show the root menu
    name: 'Transactions',
    meta: {
      title: 'Transactions',
      icon: 'lock',
      roles: ['superadmin', 'admin']    },
    children: [
      {
        path: 'info',
        component: () => import('@/views/transactions/info/index'),
        name: 'TransactionInfo',
        meta: {
          title: 'Transactions Info',
          roles: ['superadmin']
        }
      },
}

Luego dirígete a src/dashboard/views/index y modifica el código con esto:

//src/dashboard/views/index
<template>
  <div class="dashboard-editor-container">
    <panel-group @handleSetLineChartData="handleSetLineChartData" />

    <el-row style="background: #fff; padding: 16px 16px 0; margin-bottom: 32px">
      <line-chart :chart-data="lineChartData" />
    </el-row>

    <el-row :gutter="32">
      <el-col :xs="24" :sm="24" :lg="8">
        <div class="chart-wrapper">
          <raddar-chart />
        </div>
      </el-col>
      <el-col :xs="24" :sm="24" :lg="8">
        <div class="chart-wrapper">
          <pie-chart />
        </div>
      </el-col>
      <el-col :xs="24" :sm="24" :lg="8">
        <div class="chart-wrapper">
          <bar-chart />
        </div>
      </el-col>
    </el-row>

    <el-row>
      <el-col
        :xs="{ span: 24 }"
        :sm="{ span: 24 }"
        :md="{ span: 24 }"
        :lg="{ span: 24 }"
        :xl="{ span: 24 }"
        style="padding-right: 8px; margin-bottom: 30px"
      >
        <post-table />
      </el-col>
    </el-row>
  </div>
</template>

<script>
import PanelGroup from "./components/PanelGroup";
import LineChart from "./components/LineChart";
import RaddarChart from "./components/RaddarChart";
import PieChart from "./components/PieChart";
import BarChart from "./components/BarChart";
import PostTable from "./components/PostTable";
const lineChartData = {
  newVisitis: {
    expectedData: [100, 120, 161, 134, 105, 160, 165],
    actualData: [120, 82, 91, 154, 162, 140, 145],
  },
  messages: {
    expectedData: [200, 192, 120, 144, 160, 130, 140],
    actualData: [180, 160, 151, 106, 145, 150, 130],
  },
  purchases: {
    expectedData: [80, 100, 121, 104, 105, 90, 100],
    actualData: [120, 90, 100, 138, 142, 130, 130],
  },
  shoppings: {
    expectedData: [130, 140, 141, 142, 145, 150, 160],
    actualData: [120, 82, 91, 154, 162, 140, 130],
  },
};

export default {
  name: "DashboardAdmin",
  components: {
    PanelGroup,
    LineChart,
    RaddarChart,
    PieChart,
    BarChart,
    PostTable,
  },
  data() {
    return {
      lineChartData: lineChartData.newVisitis,
    };
  },
  methods: {
    handleSetLineChartData(type) {
      this.lineChartData = lineChartData[type];
    },
  },
};
</script>

Adición de componentes de interfaz de usuario

Si ha trabajado anteriormente con element-ui, estos componentes de la interfaz de usuario le resultarán muy familiares. Arriba presentamos un nuevo componente de vista, PostTable. Vamos a darle cuerpo a esto.

Cree un nuevo archivo Vue llamado PostTable.vue en src/views/dashboard/admin/components y agregue estas líneas de código:

//src/views/dashboard/admin/components/PostTable.vue
<template>
  <el-table
    v-loading="listLoading"
    :data="list"
    border
    fit
    highlight-current-row
    style="width: 100%"
  >
    <el-table-column align="center" label="ID" width="">
      <template slot-scope="{ row }">
        <span>{{ row.id }}</span>
      </template>
    </el-table-column>

    <el-table-column width="" align="center" label="Date">
      <template slot-scope="{ row }">
        <span>{{ row.timestamp | parseTime("{y}-{m}-{d} {h}:{i}") }}</span>
      </template>
    </el-table-column>

    <el-table-column width="" align="center" label="Author">
      <template slot-scope="{ row }">
        <span>{{ row.author }}</span>
      </template>
    </el-table-column>

    <el-table-column width="" label="Importance">
      <template slot-scope="{ row }">
        <svg-icon
          v-for="n in +row.importance"
          :key="n"
          icon-class="star"
          class="meta-item__icon"
        />
      </template>
    </el-table-column>

    <el-table-column class-name="status-col" label="Status" width="">
      <template slot-scope="{ row }">
        <el-tag :type="row.status | statusFilter">
          {{ row.status }}
        </el-tag>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
import { fetchList } from "@/api/article";

export default {
  name: "PostTable",
  filters: {
    statusFilter(status) {
      const statusMap = {
        published: "success",
        draft: "info",
        deleted: "danger",
      };
      return statusMap[status];
    },
  },
  data() {
    return {
      list: null,
      listLoading: true,
      listQuery: {
        page: 1,
        limit: 5,
      },
    };
  },
  created() {
    this.getList();
  },
  methods: {
    async getList() {
      this.listLoading = true;
      const { data } = await fetchList(this.listQuery);
      const items = data.items;
      this.list = items.map((v) => {
        return v;
      });
      this.listLoading = false;
    },
  },
};
</script>

Finalmente, en nuestra tabla de enrutamiento, definimos la ruta @/views/posts/index; vamos a crearlo Cree un post/index.vue en el directorio de vistas y agregue estas líneas de código:

//src/post/index.vue
<template>
  <div class="app-container">
    <el-table
      v-loading="listLoading"
      :data="list"
      border
      fit
      highlight-current-row
      style="width: 100%"
    >
      <el-table-column align="center" label="ID" width="80">
        <template slot-scope="{ row }">
          <span>{{ row.id }}</span>
        </template>
      </el-table-column>

      <el-table-column width="180px" align="center" label="Date">
        <template slot-scope="{ row }">
          <span>{{ row.timestamp | parseTime("{y}-{m}-{d} {h}:{i}") }}</span>
        </template>
      </el-table-column>

      <el-table-column width="120px" align="center" label="Author">
        <template slot-scope="{ row }">
          <span>{{ row.author }}</span>
        </template>
      </el-table-column>

      <el-table-column width="100px" label="Importance">
        <template slot-scope="{ row }">
          <svg-icon
            v-for="n in +row.importance"
            :key="n"
            icon-class="star"
            class="meta-item__icon"
          />
        </template>
      </el-table-column>

      <el-table-column class-name="status-col" label="Status" width="110">
        <template slot-scope="{ row }">
          <el-tag :type="row.status | statusFilter">
            {{ row.status }}
          </el-tag>
        </template>
      </el-table-column>

      <el-table-column min-width="300px" label="Title">
        <template slot-scope="{ row }">
          <template v-if="row.edit">
            <el-input v-model="row.title" class="edit-input" size="small" />
            <el-button
              class="cancel-btn"
              size="small"
              icon="el-icon-refresh"
              type="warning"
              @click="cancelEdit(row)"
            >
              cancel
            </el-button>
          </template>
          <span v-else>{{ row.title }}</span>
        </template>
      </el-table-column>

      <el-table-column align="center" label="Actions" width="120">
        <template slot-scope="{ row }">
          <el-button
            v-if="row.edit"
            type="success"
            size="small"
            icon="el-icon-circle-check-outline"
            @click="confirmEdit(row)"
          >
            Ok
          </el-button>
          <el-button
            v-else
            type="primary"
            size="small"
            icon="el-icon-edit"
            @click="row.edit = !row.edit"
          >
            Edit
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
import { fetchList } from "@/api/article";

export default {
  name: "Posts",
  filters: {
    statusFilter(status) {
      const statusMap = {
        published: "success",
        draft: "info",
        deleted: "danger",
      };
      return statusMap[status];
    },
  },
  data() {
    return {
      list: null,
      listLoading: true,
      listQuery: {
        page: 1,
        limit: 10,
      },
    };
  },
  created() {
    this.getList();
  },
  methods: {
    async getList() {
      this.listLoading = true;
      const { data } = await fetchList(this.listQuery);
      const items = data.items;
      this.list = items.map((v) => {
        this.$set(v, "edit", false); // https://vuejs.org/v2/guide/reactivity.html
        v.originalTitle = v.title; //  will be used when user click the cancel botton
        return v;
      });
      this.listLoading = false;
    },
    cancelEdit(row) {
      row.title = row.originalTitle;
      row.edit = false;
      this.$message({
        message: "The title has been restored to the original value",
        type: "warning",
      });
    },
    confirmEdit(row) {
      row.edit = false;
      row.originalTitle = row.title;
      this.$message({
        message: "The title has been edited",
        type: "success",
      });
    },
  },
};
</script>

Impresionante. Ahora ejecute su servidor de desarrollo con npm run dev:

Nuestra Aplicación De Demostración, Lanzada Con Npm Run DevNuestra aplicación de demostración, lanzada con npm run dev

Haga clic en Acceso y deberías ver algo como esto:

Nuestro Panel Posterior Al Inicio De SesiónNuestro panel posterior al inicio de sesión

Este es el tablero de inicio. Haga clic en Publicacionesy deberías ver algo como esto:

La Vista Publicaciones De Nuestro TableroLa vista Publicaciones de nuestro tablero

Suena como un panel de publicación de blog, ¿verdad? vue-element-admin también proporciona editores como TinyMCE y MarkdownEditor como componentes, para que pueda integrarlos directamente en este tablero.

Obtenga más información sobre vue-element-admin en su documentación aquí.

Conclusión

Los paneles de administración son una de las tareas inevitables en las que trabajará como desarrollador frontend. vue-element-admin proporciona una plantilla de código abierto y completamente gratuita para que pueda iniciar fácilmente un tablero. Los flujos de trabajo, el directorio de proyectos y la configuración de enrutamiento son lo suficientemente estándar para las aplicaciones de una sola página de nivel empresarial.

En este artículo, exploramos las características principales de vue-element-admin y luego creamos un panel de administración de publicaciones de blog.

Experimente sus aplicaciones Vue como lo hace un usuario

La depuración de aplicaciones Vue.js puede ser difícil, especialmente cuando hay docenas o incluso cientos de mutaciones durante una sesión de usuario. Si desea monitorear y rastrear las mutaciones de Vue para todos sus usuarios en producción, pruebe LogRocket. Banner De Prueba Gratuita De Logrocket Dashboardhttps://logrocket.com/regístrate/

LogRocket es como un DVR para aplicaciones web y móviles, literalmente graba todo lo que sucede en sus aplicaciones Vue, incluidas las solicitudes de red, los errores de JavaScript, los problemas de rendimiento y más. En lugar de adivinar por qué ocurren los problemas, puede agregar e informar el estado en el que se encontraba su aplicación cuando ocurrió un problema.

El complemento LogRocket Vuex registra las mutaciones de Vuex en la consola de LogRocket, brindándole contexto sobre lo que provocó un error y en qué estado se encontraba la aplicación cuando ocurrió un problema.

Modernice la forma en que depura sus aplicaciones Vue: comience a monitorear de forma gratuita.

Fuente

Artículos Relacionados

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Jenny Watson

Hi! beautiful people. I`m an authtor of this blog. Read our post – stay with us

Categorías

Artículos Relacionados

¡Descubre Hostinger, Crea tu Web y Empieza a Generar Presencia Online!

¿Buscas un hosting confiable y asequible para tu proyecto web? Hostinger te ofrece planes flexibles y potentes que se adaptan a tus necesidades. Desde sitios web personales hasta tiendas online, su tecnología de vanguardia garantiza un rendimiento excepcional.