前言
- vue的响应式
Vue中的data是响应式,当修改Vue实例中的data属性时,UI页面中data会做出响应,会被Vue监听,会被Vue实例代理,每次对data的读写都会被Vue监控,Vue会在data变化时更新UI,
const data = reactive({
loginData: {
username: "",
password: "",
},
num: count,
});
return {
...toRefs(data),
};
},
- vuex的变量改变规则
state: {
count: -1,
},
// 计算 获取 state的值
getters: {
countStatus(state) {
return state.count > 1;
},
},
// 更新状态的方法-更新state的唯一方法,(记录登录状态)commit mutations
mutations: {
setCount(state, num) {
state.count = num;
},
},
// 异步操作,可以返回promise(更改后的操作),更改数据还是传递到mutations
actions: {
setCountPromise(context, num) {
return new Promise((resolve, reject) => {
if (num > 100) {
reject("值不能大于100");
} else {
context.commit("setCount", num);
}
});
},
},
// 数据比较多,分模块
modules: {},
- vuex中的 model
export default createStore({
modules: { number, uInfo },
});
//子模块1 必须要有 namespaced:true 不然可能回因为 方法重名报错
export default {
namespaced: true,
// 全局状态初始化值
state: {
// 先判断有无本地存储,在进行需要的数据格式转化,没有的话就是{}
userInfo:
(localStorage.getItem("loginData") &&
JSON.parse(localStorage.getItem("loginData"))) ||
{},
},
// 更新状态的方法-更新state的唯一方法,(记录登录状态)commit mutations
mutations: {
},
};
//子模块2
export default {
namespaced: true,
// 全局状态初始化值
state: {
count: -1,
},
// 计算 获取 state的值
getters: {
countStatus(state) {
return state.count > 1;
},
},
// 更新状态的方法-更新state的唯一方法,(记录登录状态)commit mutations
mutations: {
setCount(state, num) {
},
},
// 异步操作,可以返回promise(更改后的操作),更改数据还是传递到mutations
actions: {
setCountPromise(context, num) {
},
},
// 数据比较多,分模块
modules: {},
};
- vue中的路由(分为 hash和history)
import {
createRouter,
//hash 和 history的使用区别
createWebHashHistory,
// createWebHistory,
} from "vue-router";
import store from "../store/index.js";
// 路由默认hash
// 可以分为 hash 和 history
//路由地址 路由名字 页面组件
const routes = [
{
path: "/login",
name: "login",
component: () => import("../views/Login/login.vue"),
},
// componet懒加载模式
// {
// path: "/",
// name: "about",
// component: AboutView,
// },
//正常是 代码没有走到 component 就引入了组件
{
path: "/layOut",
name: "layOut",
component: () => import("../views/Layout/layout.vue"),
// 重定向,子路由首页
// redirect: "/role",
//子路由 / 嵌套路由
children: [
{
path: "/role",
name: "role",
component: () => import("../views/Pages/rolesList"),
},
{
path: "/user",
name: "user",
component: () => import("../views/Pages/usersList"),
},
],
},
];
const router = createRouter({
//hash 和 history的使用区别
history: createWebHashHistory(),
routes,
});
// 路由守卫
router.beforeEach((to, from, next) => {
/**
* to:到哪个页面
* from:从哪来
* next:只有执行next页面才会进行跳转
*/
//判断用户是否登录
// console.log("store", store.state.uInfo);
const uInfo = store.state.uInfo.userInfo;
if (!uInfo.username) {
// 跳回login页面
if (to.path === "/login") {
//未登录
next();
return;
}
next("/login");
} else {
// 成功登录
next();
}
});
export default router;
- 引入element-ui 或者其他样式
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
//挂载上App对象即可
createApp(App).use(ElementPlus).mount("#app");
- 路由守卫(监测登录状态,没有登录的,回到指定页面)
// 路由守卫
router.beforeEach((to, from, next) => {
/**
* to:到哪个页面
* from:从哪来
* next:只有执行next页面才会进行跳转
*/
//判断用户是否登录
// console.log("store", store.state.uInfo);
const uInfo = store.state.uInfo.userInfo;
if (!uInfo.username) {
// 跳回login页面
if (to.path === "/login") {
//未登录
next();
return;
}
next("/login");
} else {
// 成功登录
next();
}
});
- vue的生命周期
export default {
name: "about",
setup() {
const data = reactive({
msg: "你好!",
msg2: "hellow",
num: 0,
username: "",
userInput: "",
});
// 渲染前
onBeforeMount(() => {
console.log("onBeforeMount", document.querySelector("#dom"));
});
// 渲染后
onMounted(() => {
console.log("onMounted", document.querySelector("#dom"));
setTimeout(() => {
data.msg = "hello";
}, 2000);
});
// dom更新前
onBeforeUpdate(() => {
console.log("onBeforeUpdate");
});
// dom更新后
onUpdated(() => {
console.log("onUpdated");
// 防止死循环
data.num += 1;
});
//所有要出现在页面的数据都要return
const handleClick = () => {
alert("asd");
};
const submit = () => {
alert(`${data.username}的建议是${data.userInput}`);
};
const handfocus = () => {
console.log("handfocus");
};
const handblur = () => {
console.log("handblur");
if (!data.username) {
alert("必填");
}
};
const handchange = () => {
//正则验证手机号
if (!/^[1][3,4,5,7,8,9][0-9]{9}$/.test(data.username)) {
console.log("不符合");
}
};
return {
...toRefs(data),
};
},
};
- vue页面的语法
<template>
<div>
<h2>vue3生命周期</h2>
<div id="dom">{{ msg }}</div>
<!-- v-on:事件名="事件方法" 绑定事件 -->
<!-- 事件及方法直接声明再setup -->
<button v-on:click="handleClick">click me</button>
<!-- v-model=双向绑定 -->
<!-- 之前普通html是用dom保存数据然后取值,一起传递到后端提交 -->
<!-- input 输入事件
blur: 失去焦点
focus: 获取焦点
change:内容更改 -->
<input
type="text"
placeholder="请输入姓名"
v-model="username"
@focus="handfocus"
@blur="handblur"
@change="handchange"
/>
<textarea
placeholder="请输入"
cols="30"
rows="10"
v-model="userInput"
></textarea>
{{ username }}
{{ userInput }}
<!-- @click=""绑定事件 -->
<button @click="submit">提交</button>
</div>
</template>
<template>
<h1>hello</h1>
<p v-text="name"></p>
<!-- v-text的简写 -->
<p>{{ name }}</p>
<!-- v-html -->
<p v-html="info"></p>
<!-- v-bind 动态绑定标签属性 动态绑定变量名-->
<p v-bind:data="dataVal">aa</p>
<!-- class类名绑定 -->
<!-- 可以累加类名 的style -->
<p class="text" :class="{ red: isRed }">bbb</p>
<!-- 判断语句v-if 为false 就是不存在-->
<!-- v-show 为false 只是不展示,但标签存在 -->
<p v-if="isTrue">我是if存在</p>
<p v-show="isFalse">我是ishow存在</p>
<p v-if="isFalse">if</p>
<p v-else>else</p>
<!-- v-for=(每一个对象变量,下标) + :key性能,响应式,可以单独修改那一行,不然是修改整个数组 -->
<ul>
<li v-for="(item, index) in userList" :key="index">
学生姓名:{{ item.username }} 学生年龄:{{ item.age }}
</li>
</ul>
</template>
配置
1. axios配置
首先是 service.js 其中主要是 做一些请求的初步准备,例如 请求头配置,get,post,put,delete请求的、封装,请求返回数据的处理,请求中的loading动画,返回消息的弹出框,然后export 一些需要用到的变量,比如封装好了的get,post请求,使在request.js中调用时不会有过多的参数而使用麻烦。
service.js
import axios from "axios";
import { ElMessage } from "element-plus";
import store from "../store";
import { ElLoading } from "element-plus";
let loadingObj = null;
// 使用create创建axios实例
//请求公共信息
const Service = axios.create({
timeout: 8000,
// 前缀URL
baseURL: "http://127.0.0.1:8888/api/private/v1/",
headers: {
"Content-Type": "application/json;chartset=utf-8",
Authorization: store.state.uInfo.userInfo.token,
},
});
//请求拦截-增加loading,对请求做统一处理
Service.interceptors.request.use((config) => {
loadingObj = ElLoading.service({
lock: true,
text: "Loading",
background: "rgba(0, 0, 0, 0.7)",
});
return config;
});
// 响应拦截-对返回值做统一处理
Service.interceptors.response.use(
(response) => {
loadingObj.close();
const data = response.data;
if (data.meta.status != 200 && data.meta.status != 201) {
ElMessage.error(data.meta.msg || "服务器出错");
// 请求出错
return data;
}
return data;
},
(error) => {
loadingObj.close();
ElMessage({
message: "服务器错误",
type: "error",
duration: 2000,
});
console.log(error);
}
);
//post请求 数据为 一个对象体
export const post = (config) => {
return Service({
...config,
method: "post",
data: config.data,
});
};
// get请求 数据为 params 问号传值
export const get = (config) => {
return Service({
...config,
method: "get",
params: config.data,
});
};
导入在service.js export出来的 get,post,并进行不同业务方法的封装,
request.js
import { post, get } from "./service";
// 登录
export const loginApi = (data) => {
return post({
url: "/login",
data,
});
};
// 获取用户列表
export const userListApi = (data) => {
return get({
url: "/users",
data,
});
};
// 新增用户列表s
export const userAddApi = (data) => {
return post({
url: "/users",
data,
});
};
element-ui应用
- element-ui的应用
分成 顶部面包屑区域 和 白色内容区域
<template>
<div>
<!-- 面包屑 -->
<el-breadcrumb :separator-icon="ArrowRight">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 白色内容区域 -->
<div class="page_content">
<div class="flex">
<div class="input_box">
<!-- 搜索框 -->
<el-input
v-model="searchParams.query"
placeholder="搜索关键字"
class="input-with-select"
>
<!-- 内嵌 搜索按钮 -->
<template #append>
<el-button @click="searchList"
><el-icon><Search /></el-icon
></el-button>
</template>
</el-input>
</div>
</div>
<!-- 表格 -->
<!--
el-table 的 data:要展示的数据数组
el-table-column:列 prop每条数据的对应属性
label:列标题
scope.row:相当于一条数据,通过这个属性传递到函数里
-->
<el-table :data="goodsList" style="width: 100%">
<el-table-column prop="goods_name" label="商品名" width="180" />
<el-table-column prop="goods_price" label="价格(¥)" width="180" />
<el-table-column prop="goods_weight" label="商品重量(kg)" />
<el-table-column prop="goods_state" label="商品状态">
<template #default="scope">
<!-- 转换数字为 文字,传递值到函数中 -->
<p>{{ switchState(scope.row.goods_state) }}</p>
</template>
</el-table-column>
</el-table>
<!--
v-model:currentPage 当前页
v-model:page-size 当前页展示列数
layout 选择展示那些组件
-->
<!-- 分页 -->
<el-pagination
v-model:currentPage="searchParams.pagenum"
v-model:page-size="searchParams.pagesize"
:page-sizes="[2, 5, 10, 20]"
:small="small"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="searchList"
@current-change="searchList"
/>
</div>
</div>
</template>
- 正则表达式应用
rules2: {
email: [
{
required: false,
pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
message: "请填写正确邮箱",
trigger: "blur",
},
],
mobile: [
{
required: false,
pattern:
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
message: "请填写正确手机号",
trigger: "blur",
},
],
},