实战九: Vue路由使用

文章讲述了如何在Vue项目中拆分Aside和Header组件,管理动态组件的显示,以及使用Vuex进行状态管理,包括路由控制、面包屑菜单导航和Vuexstore的使用与问题解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、 Aside和 Header,Main组件拆分

二、路由控制动态组件显示

三、面包屑菜单导航


一、 Aside和 Header,Main组件拆分

1、Invalid prop: type check failed for prop “collapse“. Expected Boolean, got Function

原先我的写法是:

既然现在传过来的是Function, 那么有两个方法, 要么将传入的参数改为Boolean, 要么将collapse指定接收的参数类型改为Function

以下为第二种方法的改法:

2、created选项名称错误写成create,导致刷新未调用接口加载数据

3、子组件和父组件

子组件路由

const routes = [
  {
    path: '/',
    name: 'Manage',
    redirect: '/home',
    component: () => import('../views/Manage.vue'),
    children: [
      {path: 'user',name: 'User',component: ()=>import ('../views/User.vue') },
      {path: 'home',name: 'Home',component: ()=>import ('../views/Home.vue') }

    ]

父组件-》子组件传参数

1)子组件设置props选项

Aside.vue

export default {
  name: "Aside",
  props: {
    isCollapse: Boolean,
    logoTextShow: Boolean
  }
}

2)父组件传参数:

manage.vue

      <el-aside :width="sideWidth+'px'" style="box-shadow: 2px 0 6px rgb(0, 21, 41 / 35%);">
        <Aside :isCollapse="isCollapse" :logoTextShow="logoTextShow"/>
      </el-aside>
    data() {
        return {
            collapseBtnClass: 'el-icon-s-fold',
            isCollapse: false,
            sideWidth: 200,
            logoTextShow: true,
        };
     },

User.vue

<template>
  <div>
    <div style="margin: 10px 0;">
      <el-input suffix-icon="el-icon-search" style="width: 200px;" placeholder="请输入姓名" class="search" v-model="username" clearable></el-input>   
      <el-input suffix-icon="el-icon-message" style="width: 200px;" placeholder="请输入邮箱" class="search" v-model="email" clearable></el-input>   
      <el-input suffix-icon="el-icon-position" style="width: 200px;" placeholder="请输入地址" class="search" v-model="address" clearable></el-input>   
      <el-button class="ml-5" type="primary" @click="load">查询</el-button>
      <el-button class="ml-5" type="warning" @click="reset">重置</el-button>

    </div>
    <div style="margin: 10px 0">
      <el-button type="primary" @click="handleAdd">新增<i class="el-icon-circle-plus-outline"></i></el-button>
      <el-popconfirm
        class="ml-5"
        confirm-button-text='确认'
        cancel-button-text='我再想想'
        icon="el-icon-info"
        icon-color="red"
        title="您确定删除吗?"
        @confirm ="delBatch" >
        <el-button type="danger" slot="reference">批量删除<i class="el-icon-remove-outline"></i></el-button>
      </el-popconfirm>

      <el-button type="primary">导入<i class="el-icon-bottom"></i></el-button>
      <el-button type="primary" class="ml-5">导出<i class="el-icon-bottom"></i></el-button>

    </div>
    <el-table :data="tableData"  border stripe :header-cell-class-name="headerBg" @selection-change="handleSelectionChange">
>
      <el-table-column type="selection" width="55"> </el-table-column>

      <el-table-column prop="id" label="ID" width="80px" align="center">
      </el-table-column>
      <el-table-column prop="username" label="用户名" width="140px" align="center">
      </el-table-column>
      <el-table-column prop="nickname" label="昵称" width="120px" align="center">
      </el-table-column>
      <el-table-column prop="email" label="邮箱" width="120px" align="center">
      </el-table-column>
      <el-table-column prop="phone" label="电话" width="120px" align="center">
      </el-table-column>
      <el-table-column prop="address" label="地址" width="200px" align="center">
      </el-table-column>
      <el-table-column label="操作" width="200px" align="center">
        <template slot-scope="scope">
          <el-button type="success" @click="handleEdit(scope.row)">编辑<i class="el-icon-edit"></i></el-button>
          <el-popconfirm
            class="ml-5"
            confirm-button-text='确认'
            cancel-button-text='我再想想'
            icon="el-icon-info"
            icon-color="red"
            title="您确定删除吗?"
            @confirm ="del(scope.row.id)" >
            <el-button type="danger" slot="reference">删除<i class="el-icon-remove-outline"></i></el-button>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    <div style="padding: 10px 0;">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="pageNum"
        :page-sizes="[2, 5, 10, 20]"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total">
      </el-pagination>
    </div>
    <el-dialog title="用户信息" :visible.sync="dialogFormVisible" width="30%">
      <el-form label-width = "80px" size = "small">
        <el-form-item label="用户名">
          <el-input v-model="form.name" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="昵称">
          <el-input v-model="form.nickname" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="邮箱">
          <el-input v-model="form.email" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="电话">
          <el-input v-model="form.phone" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="地址">
          <el-input v-model="form.address" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="save">确 定</el-button>
      </div>
    </el-dialog>
  </div>

</template>
<script>
export default {
  data(){
    return {
      tableData: [],
      total: 0,
      pageNum: 1,
      pageSize: 2,
      username: '',
      nickname: '',
      email: '',
      phone: '',
      address: '',
      dialogFormVisible: false,
      form: {},
      multipleSelection: [],
      headerBg: 'headerBg',
    }
  },
  created(){
    this.load()
  },
  methods: {
    handleSizeChange(pageSize) {
        console.log(pageSize);
        this.pageSize = pageSize;
        this.load();
    },
    handleCurrentChange(pageNum) {
        console.log(pageNum);
        this.pageNum = pageNum;
        this.load();
    },
    load() {
        //请求分页查询
        // this.request.get("http://localhost:9090/user/page?pageNum="+this.pageNum+"&pageSize="+this.pageSize+"&username="+this.username).then(res=>{
        //   console.log(res)
        //   this.tableData =res.data
        //   this.total = res.total
        // })
        this.request.get("/user/page", {
            params: {
                pageNum: this.pageNum,
                pageSize: this.pageSize,
                username: this.username,
                email: this.email,
                address: this.address
            }
        }).then(res => {
            console.log(res);
            this.tableData = res.records;
            this.total = res.total;
        })
    },
    reset() {
        this.username = '',
            this.email = '',
            this.address = '',
            this.load();
    },
    handleAdd() {
        this.dialogFormVisible = true,
            this.form = {};
    },
    save() {
        this.request.get("/user", this.form).then(res => {
            if (res) {
                this.$message.success("保存成功");
                this.dialogFormVisible = false;
                this.load();
            }
            else {
                this.$message.error("保存失败");
                this.dialogFormVisible = false;
                this.load();
            }
        });
    },
    handleEdit(row) {
        this.form = row;
        this.dialogFormVisible = true;
    },
    del(id) {
        this.request.delete("/user/" + id).then(res => {
            if (res) {
                this.$message.success("删除成功");
                this.load();
            }
            else {
                this.$message.error("删除失败");
            }
        });
    },
    handleSelectionChange(val) {
        console.log(val);
        this.multipleSelection = val;
    },
    delBatch() {
        let ids = this.multipleSelection.map(v => v.id); //[1,2,3]
        this.request.post("/user/del/batch", ids).then(res => {
            if (res) {
                this.$message.success("删除成功");
                this.load();
            }
            else {
                this.$message.error("删除失败");
            }
        });
    }

  }
}
</script>
<style scoped>
.headerBg {
  background: #eee!important;
}
</style>

二、路由控制动态组件显示

<template>
    <el-container style="min-height: 100vh;">
      <el-aside :width="sideWidth+'px'" style="box-shadow: 2px 0 6px rgb(0, 21, 41 / 35%);">
        <Aside :isCollapse="isCollapse" :logoTextShow="logoTextShow"/>
      </el-aside>
      
      <el-container >
        <el-header style="border-bottom: 1px solid #ccc;">
          <Header :collapseBtnClass="collapseBtnClass" :collapse="collapse"/>
        </el-header>

        <el-main>
          <!-- 当前页面的子路由在当前位置显示 -->
          <router-view/>
        </el-main>    
      </el-container>
    </el-container>
</template>
<script>
import Aside  from '@/components/Aside.vue'
import Header  from '@/components/Header.vue'

export default {
    data() {
        return {
            collapseBtnClass: 'el-icon-s-fold',
            isCollapse: false,
            sideWidth: 200,
            logoTextShow: true,
        };
     },

    components: {
      Aside,
      Header
    },

    methods: {
      collapse() {
          this.isCollapse = !this.isCollapse;
          if (this.isCollapse) { //收缩
              this.sideWidth = 64;
              this.collapseBtnClass = 'el-icon-s-unfold';
              this.logoTextShow = false;
          }
          else { //展开
              this.sideWidth = 200;
              this.collapseBtnClass = 'el-icon-s-fold';
              this.logoTextShow = true;
          }
      }
    }
}
</script>
<style>
.el-header {
  background-color: #fff;
  color: #333;
  line-height: 60px;
  
}

.el-aside {
  color: #333;
}

</style>

三、面包屑菜单导航

1)Vuex安装

npm i Vuex -S

2)store.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    currentPathName:''
  },
  mutations:{
    setPath(state){
      state.currentPathName= localStorage.getItem("currentPathName")
    }
  }
})

export default store

3)router 引入 store,

import store from '@/store'


const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

//路由守卫
router.beforeEach((to,from,next)=>{
  localStorage.setItem("currentPathName",to.name)
  store.commit("setPath")
  next()
})

4)main.js 引入Vuex

import store from './store'

new Vue({ router, store, render: h => h(App) }).$mount('#app')

5)面包屑使用store

Header.vue

  <div stype="flex: 1;">
    <span :class="collapseBtnClass" style="cursor: pointer; font-size: 18px" @click="collapse"></span>
    <el-breadcrumb separator="/" style="display: inline-block; margin-left: 10px;">
      <el-breadcrumb-item :to="'/'">首页</el-breadcrumb-item>
      <el-breadcrumb-item>{{currentPathName }}</el-breadcrumb-item>

    </el-breadcrumb>
  </div>
    computed: {
      currentPathName(){
        return store.state.currentPathName
      }
    },
    watch:{
      currentPathName(newVal,oldVal){
        console.log(newVal);
      }

问题:

this.store不存在

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值