1.Vue中组件的使用
1-1.全局组件和局部组件
<body>
<div id="app">
<h1>{{msg}}</h1>
<login></login>
<register></register>
<add></add>
</div>
</body>
</html>
<script src="js/axios.min.js"></script>
<script src="js/vue.js"></script>
<script>
//1.定义一个全局组件:参数1:组件名称;参数2:组件的配置对象
Vue.component('login',{
template:`<div><h2>用户登录</h2> <form action=""></form></div>`,//用来书写该组件的html代码
});
Vue.component('register',{
template:`<div><h2>用户注册</h2> <form action=""></form></div>`
});
const app = new Vue({
el:"#app",
data:{
msg:"Vue中组件的使用"
},
methods:{},
computed:{},
components:{ //注册局部组件
add:{ //添加局部组件
template:`<div><h2>用户添加</h2> <form action=""></form></div>`
}
}
});
</script>
1-2.Vue的组件中定义组件数据
- 组件中可以定义:data、methods、computed、components
- P24-27:50,向子组件传递一个动态数据,双向绑定。
P24-34:00,单向数据流。P25-20:00,通过子组件传递数据到父组件。
2.Vue-router插件的使用

2-1.vue-router之在js代码中切换路由

2-2.vue-router的基本使用之参数传递
<body>
<div id="app">
<h1>{{msg}}</h1>
<a href="#/login?name=jun&password=123">用户登录</a>
<a href="#/register/21/jun">用户注册</a>
<router-link to="/login?name=jun&password=123">用户登录</router-link>
<router-link :to="{path:'/login',query:{name:'jrh',password:1236}}">用户登录</router-link>
<router-link :to="{name:'Login',query:{name:'jrh',password:123}}">用户登录</router-link>
<router-link :to="{path:'/register/22/junhr'}">用户注册</router-link>
<router-link :to="{name:'Register',params:{id:23,name:'jun'}}">用户注册</router-link>
<router-view/>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script src="js/vue-router.js"></script>
<script>
const login = {
template:`<div><h4>用户登录</h4></div>`,
created(){
console.log("created");
console.log(this.$route);
console.log(this.$route.query.name);
console.log(this.$route.query.password);
}
};
const register = {
template:`<div><h4>用户注册</h4></div>`,
created(){
console.log(this.$route);
console.log(this.$route.params.id);
console.log(this.$route.params.name);
}
};
const router = new VueRouter({
routes:[
{path:'/login',component:login,name:'Login'},
{path:'/register/:id/:name',component:register,name:'Register'},
]
});
const app = new Vue({
el: "#app",
data: {
msg:"vue router 基本使用之参数传递"
},
methods:{},
router,
});
</script>
2-3.嵌套路由
- P30-24:02,vue-rooter中嵌套路由的使用。
3.Vue-cli脚手架
3-1.安装nodejs
- 安装nodejs:配置环境变量 =》 最终在cmd中输入
node -v 可以查看到版本信息即配置成功。Nodejs 提供了npm命令(node package manager) 即nodejs包管理工具。
- 设置nodejs本地仓库:
- npm config set cache "E:\DevProgram\nodejs\nodereps"
- npm config set prefix "E:\DevProgram\nodejs\nodereps"
- 设置淘宝镜像:
npm config set registry https://registry.npm.taobao.org 查看镜像:npm config get registry
- 验证nodejs环境配置:npm config ls
3-2.安装vue-cli
- 安装:
npm install -g vue-cli
- 配置nodejs本地仓库环境变量:E:\DevProgram\nodejs\nodereps
- 测试命令是否能够执行:
vue init
3-3.使用vue-cli创建项目
- 通过cli创建项目:
vue init webpack 项目名 根据提示一路按enter回车,直到:`? Use ESLint to lint your code?(Y/n) 可以选择no,是否建立单元测试?no,是否建立Nightwatch测试?no 。最后是否使用npm管理,回车。
- 运行这个创建好的项目(比如是hellovue项目):cd hellovue ,然后以开发模式运行:
npm run dev
- 最后浏览器访问该项目:
http://localhost:8080
3-4.vue-cli项目目录结构说明
- P34-26:00,src目录的讲解。
- node_modules 在项目提交到GitHub上时,可以排除。因为里面东西太多,而且别人在部署上传的项目时可以根据package.json自己下载(执行npm install命令时,自动下载)。
- 自己安装依赖:比如安装axios依赖:进入到项目文件夹,运行cmd:比如:
E:\hellovue>npm install axios --save (--save表示保存的意思)

- import HelloVue from '@/components/HelloVue' 这里的
@就相当于src
3-5.测试
<style scoped 如果style标签中加入了scoped,这个属性代表这个style里面的所有样式自己组件可用;如果没有加scoped属性,则代表这个style样式影响全部组件。
4.标准前端开发
- 一般开发中
components文件夹中放的是一些公共的组件,src下新建一个文件夹views放业务组件。
- 在组件的声明中写成:
component: () => import('../views/Login') 代替原来的:
export default new Router {
routes:[
path:'/login',
name:'Login',
component: ()=>import('../views/Login')
]
}
- 一般在发送axios请求前需要安装axios:
npm install axios --save,安装完成后,引入axios:import axiox from 'axios' ,发送axios请求:axios.get("http://localhost:8989/users"),但是这样不解耦。解决办法是:在src目录下创建一个utils目录,在目录里创建一个request.js ,之后发送请求的时候直接写:instance.get("/users")
import axios from 'axios'
const instance = axios.create({
baseURL: 'http://localhost:8989',
timeout: 5000,
}
);
instance.interceptors.request.use(config => {
console.log("请求拦截器");
return config;
});
instance.interceptors.response.use(response => {
console.log("响应拦截器");
return response;
},err => {
console.log("响应出现错误时进入的拦截器");
});
export default instance;
5.Vue-cli标准开发方式结合后端实现
- P36-29:14,地址栏输入非法,跳转到404页面。P37-30:00,遇到了:1.vue封装axios的post方法的跨域问题,2.新建一个config类实现WebMvcConfigurer解决跨域问题。

- 用户登录页面:输入用户名和密码后,向后端的接口发送登录请求,根据输入的信息,查询数据库,然后后端“告诉”前端是否登录成功。
在后端生成一个token,同时将token保存到后端的redis里。
- 启动虚拟机,输入:
docker run -d --name redis01 -p 6379:6379 redis:5.0.14
- P37-36:58,登录成功后,显示欢迎xxx,
<span v-show="admin.username">欢迎: {{admin.username}}</span>,进入员工管理系统主页。P37-45:00,解决同一个路由多次切换报错的问题。
- P38-5:17,当首次点员工管理按钮时,就会发送一个查询所有员工的请求。
5-1.登录功能实现
后端AdminServiceImpl.java
@Service("adminService")
@Transactional
public class AdminServiceImpl implements AdminService {
@Resource
private AdminDao adminDao;
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public Admin login(Admin admin) {
Admin adminDB = adminDao.findByUserName(admin.getUsername());
if(adminDB == null) throw new RuntimeException("用户名输入错误!");
if(!adminDB.getPassword().equals(admin.getPassword())) throw new RuntimeException("密码输入错误!");
return adminDB;
}
@Override
public Admin queryById(Integer id) {
return this.adminDao.queryById(id);
}
}
后端AdminController.java
@RestController
@CrossOrigin(origins="*",allowCredentials = "true",allowedHeaders = "",methods = {})
public class AdminController {
private static final Logger log = LoggerFactory.getLogger(AdminController.class);
@Resource
private AdminService adminService;
@Autowired
private RedisTemplate redisTemplate;
@DeleteMapping("/token")
public void token(String token) {
redisTemplate.delete(RedisPrefix.TOKEN + token);
}
@GetMapping("/token")
public Admin admin(String token) {
log.info("接收的token信息:{}",token);
return (Admin) redisTemplate.opsForValue().get(RedisPrefix.TOKEN + token);
}
@PostMapping("login")
public Map<String,Object> login(@RequestBody Admin admin, HttpSession session) {
log.info("admin-username:{},admin-password:{}",admin.getUsername(),admin.getPassword());
Map<String,Object> result = new HashMap<>();
try {
Admin adminDB = adminService.login(admin);
String token = session.getId();
redisTemplate.opsForValue().set(RedisPrefix.TOKEN+token,adminDB,30, TimeUnit.MINUTES);
result.put("success", true);
result.put("token", token);
} catch (Exception e) {
e.printStackTrace();
result.put("success", false);
result.put("msg", e.getMessage());
}
return result;
}
}
5-2.员工页面展示
后端EmpController.java
@RestController
@CrossOrigin
public class EmpController {
private static final Logger log = LoggerFactory.getLogger(EmpController.class);
@Resource
private EmpService empService;
@GetMapping("/emp")
public ResponseEntity<Emp> queryById(Integer id) {
return ResponseEntity.ok(this.empService.queryById(id));
}
@GetMapping("/emps")
public List<Emp> emps() {
List<Emp> emps = empService.queryAll();
return emps;
}
@DeleteMapping("/emp")
public ResponseEntity<Boolean> deleteById(Integer id) {
log.info("要删除的员工id是:{}",id);
return ResponseEntity.ok(this.empService.deleteById(id));
}
@PostMapping("/emp")
public ResponseEntity<Emp> update(@RequestBody Emp emp) {
if (StringUtils.isEmpty(emp.getId())) {
log.info("当前保存的员工信息:{}"+emp.toString());
return ResponseEntity.ok(this.empService.insert(emp));
} else {
log.info("当前修改的员工信息:{}"+emp.toString());
return ResponseEntity.ok(this.empService.update(emp));
}
}
}
5-3.Vue-cli项目部署
方案一
- 在项目根目录中执行命令:
npm run build 【注意】:vue脚手架打包的项目必须在服务器上运行不能直接双击运行。打包完成后为dist文件夹。
- 将dist文件夹直接通过docker部署到nginx里面,前端系统一般不建议部署到tomcat里面,因为tomcat属于动态服务器。直接启动nginx是不行的:
docker run -d --name nginx01 -p 80:80 nginx:1.19.10,启动nginx时,一定要把HTML目录映射,让其文件夹中装的是需要部署的dist文件,先进入普通启动的nginx里:docker exec -it(交互的方式) nginx01 bash 然后切换到nginx的家目录:cd /usr/share/nginx/html,日后只需要映射到这个目录就行,将需要部署的dist文件上传到/root目录,P41-17:09
[root@192 ~]
[root@192 ~]
dist dockerfile ems html redisConf redisData tomcat-8.0.tar
[root@192 ~]
[root@192 ~]
- 按上述方法启动完nginx后,在地址栏输入:
http://192.168.200.130/index.html就能访问到部署的项目页面。但目前还无法和后端交互。
方案二

- P41-18:34
P42-3:07,docker run -d -p 80:80 --name nginx01 -v /root/html/:/usr/share/nginx/html nginx:1.19.10。地址栏访问:http://192.168.200.130/dist/index.html。
6.Vuex-官方状态管理器
- 在vue-cli项目中安装vuex:
npm install vuex --save,新建一个文件夹P43-20:00:store(代表存储状态的意思),在store文件夹下新建一个入口文件:index.js
- 配置Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({});
export default store;
- 在main.js中引入stroe并注册到vue实例
import Vue from 'vue'
import App from './App'
import router from './router'
import store from "./stroe";
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
store,
})
6-1.state属性
const store = new Vuex.Store({
state:{
counter:0,
},
}
{{$store.state.counter}} ===> {{this.$store.state.counter}}
6-2.mutations属性
const store = new Vuex.Store({
state:{
counter:0,
},
mutations:{
increment(state){
state.counter++
},
decrement(state){
state.counter--
}
}
});
this.$store.commit('decrement');
this.$store.commit('increment');
mutations:{
addCount(state,counter){
console.log(counter);
return state.counter += counter ;
}
}
this.$store.commit('addCount',11);
6-3.getters属性
- 官方: 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
- 作用: 用来定义对共享的数据的计算相关的一系列函数 相当于 computed 属性 会对结果进行缓存
getters:{
mathSqrts(state){
console.log("--------");
return state.counter*state.counter;
},
mathSqrtsNumber(state,getters){
return getters.mathSqrts*3;
},
mathSqrtsNumbers(state,getters){
return function (number){
return number;
}
}
}
# 3.使用
- 1.{{$store.getters.mathSqrts}}
- 2.{{$store.getters.mathSqrtsNumber}}
- 3.{{$store.getters.mathSqrtsNumbers(3)}}