任务四:Vue2 CLI静态展示版学生管理系统(只有页面UI,无交互逻辑)

一、MyTip.vue

<template>
    <div class="tip" :class="type">
        {{ msg }}
    </div>
</template>
<script>
export default {
    props: {
        msg: String,
        type: { type: String, default: "success" }
    }
}
</script>
<style scoped>
.tip {
    position: fixed;
    top: 30px;
    left: 50%;
    transform: translateX(-50%);
    padding: 10px 20px;
    border-radius: 4px;
    color: #fff;
    z-index: 9999;
}

.success {
    background: #67c23a;
}

.error {
    background: #f56c6c;
}
</style>

二、StudentCard.vue

<template>
    <div class="card" v-bind="$attrs">
        <!-- 默认插槽 -->
        <slot></slot>
        <!-- 具名插槽 -->
        <div class="card-footer">
            <slot name="footer"></slot>
        </div>
    </div>
</template>
<script>
export default {
    inheritAttrs: false
}
</script>
<style scoped>
.card {
    border: 1px solid #ccc;
    padding: 14px;
    border-radius: 6px;
    width: 260px;
}

.card-footer {
    margin-top: 10px;
    border-top: 1px solid #eee;
    padding-top: 8px;
}
</style>

三、TableRowRender.vue

<script>
export default {
    props: ["text"],
    render(h) {
        return h("span", {
            style: {
                color: "#409eff",
                fontWeight: "bold"
            }
        }, this.text)
    }
}
</script>

四、main.js

import Vue from 'vue'
import App from './App.vue'
import MyTip from './components/MyTip.vue'

// 全局自定义指令 v‑highlight
Vue.directive('highlight', {
  bind(el, binding) {
    el.style.backgroundColor = binding.value ? '#fff2cc' : ''
  },
  update(el, binding) {
    el.style.backgroundColor = binding.value ? '#fff2cc' : ''
  }
})

// Vue.use 自定义插件语法演示
const tipPlugin = {
  install(Vue) {
    const TipConstructor = Vue.extend(MyTip)
    Vue.prototype.$showTip = function (msg, type = "success") {
      const instance = new TipConstructor({
        propsData: { msg, type }
      })
      instance.$mount()
      document.body.appendChild(instance.$el)
      setTimeout(() => {
        document.body.removeChild(instance.$el)
      }, 2000)
    }
  }
}
Vue.use(tipPlugin)

Vue.config.productionTip = false

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

五、App.vue

<template>
  <div class="layout">
    <!-- 侧边导航:仅切换页面视图,无业务逻辑 -->
    <aside class="sidebar">
      <h2>📚学生管理系统</h2>
      <div class="menu-item" @click="pageKey = 'home'">首页</div>
      <div class="menu-item" @click="pageKey = 'list'">学生列表</div>
      <div class="menu-item" @click="pageKey = 'add'">新增学生</div>
    </aside>

    <main class="main">
      <!--页面1:仪表盘首页-->
      <div v-if="pageKey === 'home'">
        <h1>欢迎来到学生信息管理面板</h1>
        <p>我是计应08班的周长</p>
        <div style="display:flex;gap:15px;margin-top:20px;">
          <!--演示 $attrs 非特定属性,data-static为非prop属性-->
          <StudentCard data-static="静态测试">
            <h3>综合项目静态页面</h3>
            <p>我喜欢打篮球</p>
            <template #footer>
              <span>我的学号是10260916</span>
            </template>
          </StudentCard>
        </div>
        <div style="margin-top:20px;">
          <button @click="$showTip('插件弹窗演示')">测试插件弹窗(Vue.use)</button>
        </div>
      </div>

      <!--页面2:学生列表【静态表格,按钮仅样式,点击不修改数据】-->
      <div v-if="pageKey === 'list'">
        <h2>学生信息列表</h2>
        <table border="1" cellpadding="8" cellspacing="0" style="background:#fff;width:100%;">
          <thead>
            <tr>
              <th>ID</th>
              <th>姓名</th>
              <th>年龄</th>
              <th>状态</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <!-- v-highlight自定义指令演示 -->
            <tr v-for="item in staticStudentList" :key="item.id" v-highlight="item.highlight">
              <td>
                <TableRowRender :text="item.id"></TableRowRender>
              </td>
              <td>{{ item.name }}</td>
              <td>{{ item.age }}</td>
              <td>{{ item.highlight ? "已标记" : "正常" }}</td>
              <td>
                <!--按钮仅UI展示,点击无业务效果-->
                <button>标记/取消标记</button>
                <button>编辑</button>
                <button>删除</button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <!--页面3:新增学生表单【静态表单,输入框可以打字,但不会提交保存】-->
      <div v-if="pageKey === 'add'">
        <h2>新增学生(静态表单)</h2>
        <div style="background:#fff;padding:20px;width:400px;">
          <!--$refs语法演示,mounted获取DOM,仅演示代码,不做业务逻辑-->
          <div>姓名:<input ref="nameRef" v-model="form.name" placeholder="请输入姓名" /></div>
          <div style="margin-top:8px">年龄:<input v-model.number="form.age" type="number" placeholder="请输入年龄" /></div>
          <div style="margin-top:12px;">
            <button>保存提交</button>
            <button>重置</button>
            <button @click="pageKey = 'list'">返回列表</button>
          </div>
        </div>
      </div>
    </main>
  </div>
</template>

<script>
import StudentCard from './components/StudentCard.vue'
import TableRowRender from './components/TableRowRender.vue'

export default {
  components: { StudentCard, TableRowRender },
  data() {
    return {
      pageKey: 'home',
      // 静态模拟表单,可输入,但不会提交保存
      form: {
        name: "",
        age: 18
      },
      // 写死静态表格数据,不会被修改
      staticStudentList: [
        { id: 1, name: "张三", age: 18, highlight: false },
        { id: 2, name: "李四", age: 19, highlight: true },
        { id: 3, name: "王五", age: 20, highlight: false },
        { id: 4, name: "周长", age: 28, highlight: true }
      ]
    }
  },
  mounted() {
    // $refs语法演示,仅获取DOM,无业务逻辑
    if (this.$refs.nameRef) {
      console.log("$refs获取输入框DOM:", this.$refs.nameRef)
    }
  }
}
</script>

<style scoped>
.layout {
  display: flex;
  height: 100vh;
  margin: 0;
}

.sidebar {
  width: 220px;
  background: #304156;
  color: #fff;
  padding: 20px 10px;
}

.menu-item {
  padding: 10px 8px;
  cursor: pointer;
  margin: 6px 0;
}

.menu-item:hover {
  background-color: #48576a;
}

.main {
  flex: 1;
  padding: 24px;
  background: #f5f7fa;
  overflow: auto;
}
</style>

六、运行效果

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值