Vue进阶
Vue cli
一、Vue cli 概述
- CLI 全称是 Commond Line Interface,翻译为命令行界面,俗称脚手架。
- VueCLI是一个官方发布vue.js项目脚手架。
- 用VueCLI 可快速搭建Vue开发环境以及对应webpack配置。
二、环境搭建
1、下载 node.js
- 下载地址:https://nodejs.cn/download/

2、安装 node.js
(1)傻瓜式安装
 一路下一步操作(安装路径按自己的意思来),安装完成后会自动添加到环境变量中,这个时候你的cmd就会多了两个命令。
- node:进入node.js环境
- npm:安装模块用
(2)测试安装成功

3、安装Vue-cli
(1)打开cmd窗口输入命令
// 速度慢
npm install -g @vue/cli
// 使用镜像,速度快
npm install -g @vue/cli --registry=https://registry.npm.taobao.org

(2)测试Vue-cli安装成功
vue -v
或者
vue --version

Vue 项目基础操作
一、创建项目
1、进入要创建项目的目录,创建项目
vue create 项目名

2、选择模板,这时候按下键,选择最后一个自定义,回车执行

3、按上下键移动(带*的),空格选择,回车键执行

4、选择版本vue3.回车键执行

5、先输入y,回车键执行后选择In package.json,回车键执行

6、再次输入y,回车键执行,再次回车键执行

7、进入项目并启动


8、使用VSCode打开day0424

项目名
├── node_modules -- 项目的依赖
├── public -- 文件夹
├    ├── favicon.ico -- 网站顶部小图标
├    └── index.html -- 单页面开发,项目唯一页面
├── src -- 文件夹,主要代码都在里面
├    ├── assets -- img,js,css,都可以放在这里
├    ├── components -- 小组件,放在页面组件中的
├    ├── store -- 安装了vuex就会生成
├    ├── router -- 安装了vue-router就会生成,配置路由
├    ├── views -- 页面组件存放在这
├    ├── App.vue -- 根组件,靠它和唯一的页面连接的
├    └── main.js -- 整个项目的入口,引入全局配置
├── .gitignore -- git版本管理
├── babel.config.js -- babel的配置,不用管
├── jsconfig.json
├── package.json -- 项目的配置,和依赖的模块都在这
├── package-lock.json
├── README.md -- 项目的介绍
└── vue.config.js -- vue的配置信息
9、开启VSCode,启动项目(关掉之前的cmd)

- 注意:这里在VSCode 中启动项目时,要先重启一下VSCode,重新打开终端。
  
10、VSCode安装识别vue内容的插件
- 保存后,项目自启动(热部署)

二、组件编写及使用
1、在views文件中创建自己的Vue文件,First.vue
<template>
    <div id="first">
        Hello World!
    </div>
</template>
<style>
    #id{
        width: 100px;
        height: 100px;
        background-color: aqua;
    }
</style>
<script>
// export default 的作用相当于:Vue.createApp(),默认的出口
export default {
    
}
</script>
2、在router的index.js中注册路由
import { createRouter, createWebHistory } from 'vue-router'
// 引入first.vue
import first from "../views/first.vue"
// 注册路由
const routes = [
  {
    path: '/f',
    // name: 'first', 可以不要
    // component的名字与import处对应
    component: first
  },
]
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})
export default router
3、在APP.vue中书写路由导航
- nav:导航标签
- to:注册路由的路径
- :to去的view页面 -
- 注意:vue的模版中只有能一个根节点,所以在template中插入第二个元素就会报错
<template>
    <div id="first">
        Hello World!
    </div>
</template>
<style>
    #first{
        width: 100px;
        height: 100px;
        background-color: aqua;
    }
</style>
<script>
// export default 的作用相当于:Vue.createApp(),默认的出口
export default {
    
}
</script>
4、测试

 
5、在first.vue中书写数据解析代码
<template>
  <div id="first">
    <table border="1" cellpadding="0" cellspacing="0" width="500" align="center">
      <tr>
        <th>学号</th>
        <th>姓名</th>
        <th>年龄</th>
        <th>邮箱</th>
        <th>头像</th>
        <th>操作</th>
      </tr>
      <tr align="center" v-for="(stu,index) in students" v-bind:key="index">
        <td>{{stu.stuId}}</td>
        <td>{{stu.stuName}}</td>
        <td>{{stu.stuAge}}</td>
        <td>{{stu.stuEmail}}</td>
        <td>{{stu.stuPhoto}}</td>
        <td>
            <a href="javascript:void(0)" >删除</a>  
            <a href="javascript:void(0)" >编辑</a>
        </td>
      </tr>
    </table>
  </div>
</template>
<style>
    #first{
        width: 500px;
        margin: auto;
    }
</style>
<script>
// export default 的作用相当于:Vue.createApp(),默认的出口
    export default {
        data() {
            return {
                students:[
                    {stuId:1,stuName:"mary",stuAge:18,stuEmail:"mary@qq.com",stuPhoto:"mary.jpg"},
                    {stuId:2,stuName:"tom",stuAge:18,stuEmail:"tom@qq.com",stuPhoto:"tom.jpg"},
                    {stuId:3,stuName:"lucy",stuAge:18,stuEmail:"lucy@qq.com",stuPhoto:"lucy.jpg"}
                ]
            }
        },
        methods: {
            
        },
    };
</script>

axios的使用
1、axios的安装
npm install axios

2、VsCode项目中加载axios

3、后端代码准备
(1)引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--依赖父亲maven-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.11</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.etime</groupId>
    <artifactId>day0423</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>day0423</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--在SpringBoot在引入web,由启动器 (starter) 完成-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--引入Lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
        <!--数据库相关-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
            <scope>runtime</scope>
        </dependency>
        <!--单元测试相关-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--引入热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!-- 导入Mybatis-Plus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
    </dependencies>
    <!--构建插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
(2)实体类
package com.etime.day0423.pojo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student {
    @TableId("sid")
    private int sid;
    private String sname;
    private int cid;
    private int sage;
    private String email;
    private String sphoto;
}
(3)持久层
package com.etime.day0423.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.etime.day0423.pojo.Student;
import org.springframework.stereotype.Repository;
//
@Repository
public interface StudentMapper extends BaseMapper<Student> {
/*
    BaseMapper<Student>:继承父接口,并指定类型
 */
}
(4)业务逻辑层
- 实现类中
package com.etime.day0423.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.etime.day0423.mapper.StudentMapper;
import com.etime.day0423.pojo.Student;
import com.etime.day0423.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentMapper studentMapper;
    @Override
    public int addStudent(Student student) {
        return studentMapper.insert(student);
    }
    @Override
    public int deleteStudent(int sid) {
        return studentMapper.deleteById(sid);
    }
    @Override
    public int updateStudent(Student student) {
        return studentMapper.updateById(student);
    }
    @Override
    public List<Student> getAllStudent() {
        List<Student> list = studentMapper.selectList(null);
        return list;
    }
    @Override
    public Page<Student> getStudentByPage(int currentPage,int size) {
        Page<Student> page = new Page<>(currentPage,size);
        return studentMapper.selectPage(page,null);
    }
    @Override
    public Page<Student> getStudentBySname(String sname, int current, int size) {
        QueryWrapper<Student> wrapper = new QueryWrapper<>();
        wrapper.like("sname",sname);
        Page<Student> page = new Page<>(current,size);
        return studentMapper.selectPage(page,wrapper);
    }
}
(5)控制层
package com.etime.day0423.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.etime.day0423.pojo.Student;;
import com.etime.day0423.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@CrossOrigin
public class StudentController {
    @Autowired
    private StudentService studentService;
    @GetMapping("/student")
    public List<Student> getAllStudent() {
        List<Student> list = studentService.getAllStudent();
        return list;
    }
    @PostMapping("/student")
    public boolean addStudent(Student student){
        return studentService.addStudent(student) != 0 ? true:false;
    }
    @DeleteMapping("/student/{sid}")
    public boolean deleteStudent(@PathVariable("sid") int sid){
        return studentService.deleteStudent(sid) != 0 ? true:false;
    }
    @PutMapping("/student")
    public boolean updateStudent(Student student){
        return studentService.updateStudent(student) != 0 ? true:false;
    }
    @GetMapping("/student/page")
    public Page<Student> getStudentByPage(int currentPage,int size){
        return studentService.getStudentByPage(currentPage,size);
    }
    @GetMapping("/student/like")
    public Page<Student> getStudentByName(String sname,int currentPage,int size){
        return studentService.getStudentBySname(sname,currentPage,size);
    }
}
4、编写前端代码,修改first.vue中代码
<template>
  <div id="first">
    <table border="1" cellpadding="0" cellspacing="0" width="500" align="center">
      <tr>
        <th>学号</th>
        <th>姓名</th>
        <th>年龄</th>
        <th>邮箱</th>
        <th>头像</th>
        <th>操作</th>
      </tr>
      <tr align="center" v-for="(stu,index) in students" v-bind:key="index">
        <td>{{stu.sid}}</td>
        <td>{{stu.sname}}</td>
        <td>{{stu.sage}}</td>
        <td>{{stu.email}}</td>
        <td>
            <img :src="'http://localhost:8888/teacher/'+stu.sphoto" style="width:50px;height50px; border-radius: 50%;">
        </td>
        <td>
            <a href="javascript:void(0)" >删除</a>  
            <a href="javascript:void(0)" >编辑</a>
        </td>
      </tr>
    </table>
    <div style="width: 500px; margin: auto; text-align: right">
        <a href="javascript:void(0)" @click="getStudentByPage(1)">首页</a>
        <a href="javascript:void(0)" @click="getStudentByPage(prevPage)">上一页</a>
        {{ current }}/{{ pages }}
        <a href="javascript:void(0)" @click="getStudentByPage(nextPage)">下一页</a>
        <a href="javascript:void(0)" @click="getStudentByPage(pages)">尾页</a>
  </div>
  </div>
</template>
<style>
    #first{
        width: 500px;
        margin: auto;
    }
</style>
<script>
    import axios from 'axios'
// export default 的作用相当于:Vue.createApp(),默认的出口
    export default {
        data() {
            return {
                students:"",
                current: 1,
                size: 5,
                pages: "",
                prevPage: "",
                nextPage: "",
            }
        },
        methods: {
            getStudentByPage(page) {
                let content = new URLSearchParams();
                content.append("currentPage", page);
                content.append("size", this.size);
                axios({
                    url: "http://localhost:8888/student/page",
                    method: "get",
                    params: content,
                }).then((resp) => {
                    console.log(resp.data);
                    this.students = resp.data.records;
                    this.pages = resp.data.pages;
                    this.current = resp.data.current;
                    if (this.current == 1) {
                    this.prevPage = 1;
                    } else {
                    this.prevPage = this.current - 1;
                    }
                    if (this.current == this.pages) {
                    this.nextPage = this.pages;
                    } else {
                    this.nextPage = this.current + 1;
                    }
                });
                },
        },
        created() {
            this.getStudentByPage(1);
        },
    };
</script>

Vue路由
一、路由概述
- 路由的本质:一种对应关系,(该处的路由含义同之前nodejs的路由)。
- 路由根据不同的url请求,,返回对应不同的资源。那么url地址和真实的资源之间就有一种对应的关系,就是路由。
二、一级路由示例代码
1、创建多个vue文件
(1)FoundMusic.vue
<template>
    <h1>发现音乐</h1>
</template>
<style >
</style>
(2)MyMusic.vue
<template>
    <h1>我的音乐</h1>
</template>
<style >
</style>
(3)Interest.vue
<template>
    <h1>关注</h1>
</template>
<style >
</style>
2、注册路由
import { createRouter, createWebHistory } from 'vue-router'
import first from "../views/first.vue"
import MyMusic from "../views/MyMusic.vue"
import Interest from "../views/Interest.vue"
// 注册路由
const routes = [
  {
    path: '/f',
    // name: 'first', 可以不要
    // component的名字与import处对应
    component: first
  },
  {
    // 方式二
    path: '/found',
    component: () => import(/* webpackChunkName: "about" */ '../views/FoundMusic.vue')
  },
  {
    path: '/my',
    component: MyMusic
  },
  ,
  {
    path: '/interest',
    component: Interest
  },
]
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})
export default router
3、在App.vue中编写代码
<template>
  <nav>
    <router-link to="/f">first</router-link> |
     <router-link to="/found">发现音乐</router-link> |
      <router-link to="/my">我的音乐</router-link> |
       <router-link to="/interest">关注</router-link>
    <router-view/>
  </nav>
</template>
<style>
  
</style>
4、结果

二、二级路由
1、childFound.vue
<template>
    <h1>排行榜</h1>
</template>
2、childFound02.vue
<template>
    <h1>网络热歌</h1>
</template>
3、注册二级路由,在index.js的"/found"中
 {
    // 方式二
    path: '/found',
    component: () => import(/* webpackChunkName: "about" */ '../views/FoundMusic.vue'),
    children:[
      {
        path: '/child01',
        component:() => import('../views/childFound.vue')
      },
      {
        path: '/child02',
        component:() => import('../views/childFound02.vue')
      }
    ]
  }
4、修改FoundMusic.vue中代码
<template>
    <nav>
        <router-link to="/child01">排行榜</router-link>> |
        <router-link to="/child02">网络热歌</router-link>>
        <router-view/>
    </nav>
</template>
<style >
</style>
5、测试结果

VueX
一、VUeX概述
vue官方提供的独立于组件体系之外的,管理公共数据的工具。
二、vuex分块
1、state
 state: 统一定义公共数据(类似于data(){return {a:1, b:2,xxxxxx}})
2、mutations
 mutations : 使用它来修改数据(类似于methods)
3、getter
 类似于computed(计算属性,对现有的状态进行计算得到新的数据-------派生 )
4、action
 actions: 发起异步请求
5、modules
 modules: 模块拆分
三、示例代码
1、在store文件夹的index.js中设计共享函数
import { createStore } from 'vuex'
export default createStore({
  state: {
    sid:"",
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})
2、在first.vue中设计数据及点击事件
(1)点击事件
<td>
            <a href="javascript:void(0)" @click="deleteStudentBySid(stu.sid)">删除</a>  
            <a href="javascript:void(0)" @click="updateStudentBySid(stu.sid)">编辑</a>
        </td>
(2)点击事件函数
updateStudentBySid(sid){
     // 切换当前路由到editStudent
     this.$router.replace("/edit");
     // 将sid放入vuex的state中
     this.$store.state.sid = sid;
},
(3)注意事项
 点击事件中我们要在当前页面 加载其他组件用于替换当前组件,所以 用到了this.$router.replace(“/edit”);并且写组件需要在在router中的index.js中注册。
3、注册新组件
(1)编写新组件editStudent.vue页面
<template>
     <form>
        学号<input name="sid" type="text" ><br >
        姓名<input name="sname" type="text" ><br >
        年龄<input name="sage" type="text" ><br >
        性别 <input name="sgender" type="radio" value="男">男 
        <input name="sgender" type="radio" value="女">女<br >
        邮箱<input name="semail" type="text" ><br >
        <input type="button" value="保存" >
  </form>
</template>
<style >
</style>
<script>
    export default {
        data() {
            return {
                
            }
        },
        methods: {
            
        },
        created() {
            // 获取vuex的state的sid的值
            let sid = this.$store.state.sid;
            console.log("eidtStudent中获取到的"+sid);
        },
    }
</script>
(2)注册editStudent.vue
 {
    path: '/edit',
    component: editStudent
  }
(3)测试

解决根目录问题
1、警告提示

2、注册路由修改,在index.js中
{
    path: '/',
    // name: 'first', 可以不要
    // component的名字与import处对应
    component: first
  },
  {
    path: '/f',
    // name: 'first', 可以不要
    // component的名字与import处对应
    component: first
  },
3、测试
 当你点击其他组件,回到上面我们修改的注册路由时,就会看到只有服务器地址,没有注册的path。
```(2)注册editStudent.vue
 {
    path: '/edit',
    component: editStudent
  }
(3)测试











