文章目录
- Vue3
- vue3与vue2区别
- Vue3全局api
- Vue3挂载全局axios
- 工具库简单使用
- 配置请求代理解决跨域
- vue3使用script setup 语法糖
- pinia 状态管理
Vue3
1.创建vue3
1.1 使用vue-cli创建
vue ui
或者 vue create project
1.2 使用vite创建(node版本>12.0.0.0)
兼容注意:必须安装Volar插件 ,使用vscode
安装vite
npm init vite@latest
或者
npm init @vitejs/app
//安装vite同时创建vite项目
npm init vite@latest my-vue-app --template vue
//vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import {loadEnv}from 'vite'
import path from "path";
export default defineConfig({
plugins: [vue()],
base: "./", // 类似publicPath,'./'避免打包访问后空白页面,要加上,不然线上也访问不了
mode:"",//设置开发模式还是生成模式
server: {
https: false, // 是否开启 https
open: false, // 是否自动在浏览器打开
host: "127.0.0.1",//域名
port: 3000, // 端口号
proxy: {
"/api": {
target: "", // 后台接口
changeOrigin: true,//跨域处理
secure: false, // 如果是https接口,需要配置这个参数
// ws: true, //websocket支持
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
resolve: {
alias: {
// 如果报错__dirname找不到,需要安装node,执行npm install @types/node --save-dev
"@": path.resolve(__dirname, "src"),
"@assets": path.resolve(__dirname, "src/assets"),
"@components": path.resolve(__dirname, "src/components"),
"@images": path.resolve(__dirname, "src/assets/images"),
"@views": path.resolve(__dirname, "src/views"),
"@store": path.resolve(__dirname, "src/store"),
},
},
/*
build: {
outDir: "dist",
// 9月更新
assetsDir: "assets", //指定静态资源存放路径
sourcemap: false, //是否构建source map 文件
terserOptions: {
// 生产环境移除console
compress: {
drop_console: true,
drop_debugger: true,
},
},
},
*/
},
// 引入第三方的配置
optimizeDeps: {
//include: ["element-plus/lib/locale/lang/zh-cn"],//举例
},
});
// Vue.config.js 配置选项
module.exports = {
// 选项
// 基本路径
publicPath: "./",
// 构建时的输出目录
outputDir: "dist",
// 放置静态资源的目录
assetsDir: "static",
// html 的输出路径
indexPath: "index.html",
//文件名哈希
filenameHashing: true,
//用于多页配置,默认是 undefined
pages: {
index: {
// page 的入口文件
entry: 'src/index/main.js',
// 模板文件
template: 'public/index.html',
// 在 dist/index.html 的输出文件
filename: 'index.html',
// 当使用页面 title 选项时,
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: 'Index Page',
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'index']
},
// 当使用只有入口的字符串格式时,
// 模板文件默认是 `public/subpage.html`
// 如果不存在,就回退到 `public/index.html`。
// 输出文件默认是 `subpage.html`。
subpage: 'src/subpage/main.js'
},
// 是否在保存的时候使用 `eslint-loader` 进行检查。
lintOnSave: true,
// 是否使用带有浏览器内编译器的完整构建版本
runtimeCompiler: false,
// babel-loader 默认会跳过 node_modules 依赖。
transpileDependencies: [ /* string or regex */ ],
// 是否为生产环境构建生成 source map?
productionSourceMap: true,
// 设置生成的 HTML 中 <link rel="stylesheet"> 和 <script> 标签的 crossorigin 属性。
crossorigin: "",
// 在生成的 HTML 中的 <link rel="stylesheet"> 和 <script> 标签上启用 Subresource Integrity (SRI)。
integrity: false,
// 调整内部的 webpack 配置
configureWebpack: () => {}, //(Object | Function)
chainWebpack: () => {},
// 配置 webpack-dev-server 行为。
devServer: {
open: process.platform === 'darwin', //配置自动启动浏览器
host: '0.0.0.0',
port: 8080,
https: false,
hotOnly: false // 热更新
// 查阅 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli/cli-service.md#配置代理
proxy: {
'/api': {
target: "http://app.rmsdmedia.com",
changeOrigin: true,
secure: false,
pathRewrite: {
"^/api": ""
}
},
'/foo': {
target: '<other_url>'
}
}, // string | Object
before: app => {}
},
// CSS 相关选项
css: {
// 将组件内的 CSS 提取到一个单独的 CSS 文件 (只用在生产环境中)
// 也可以是一个传递给 `extract-text-webpack-plugin` 的选项对象
extract: true,
// 是否开启 CSS source map?
sourceMap: false,
// 为预处理器的 loader 传递自定义选项。比如传递给
// Css-loader 时,使用 `{ Css: { ... } }`。
loaderOptions: {
css: {
// 这里的选项会传递给 css-loader
},
postcss: {
// 这里的选项会传递给 postcss-loader
}
},
// 为所有的 CSS 及其预处理文件开启 CSS Modules。
// 这个选项不会影响 `*.vue` 文件。
modules: false
},
// 在生产环境下为 Babel 和 TypeScript 使用 `thread-loader`
// 在多核机器下会默认开启。
parallel: require('os').cpus().length > 1,
// PWA 插件的选项。
// 查阅 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli-plugin-pwa/README.md
pwa: {},
// 三方插件的选项
pluginOptions: {
// ...
}
}
2.setup函数
组件中所用到的:数据 方法等,均需配置在setup中
1.返回一个对象,则对象中的属性,方法,在模板中可以直接使用(常用)
2.返回一个渲染函数,则可以自定义渲染内容
//注意点:
setup不能是一个async函数,因为返回值不再是return的对象,而是proise,模板中看不到reutrn对象中的熟悉。(注意:后期也可以返回一个promise实例,但是需要Suspense与异步组件(defineAsyncComponents)的配合)
<template>
<h1>一个人的信息</h1>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @clcik="sayHello">sayHello</button>
</template>
<script>
setup(){
let name='zs',
let age=18
function sayHello(){
alert(`我叫${name},我${age}岁了!`)
}
return { //返回一个对象
name,
age,
sayHello
}
}
</script>
3.ref函数(修改数据需要.value)
//引入ref函数
import { ref } from "vue";
setup() {
let name = ref("zs"); //响应式数据 ref()
let job=ref({
type:"前端工程师",
salary:"30k"
})
function sayhi() {
alert("zs");
}
function changeInfo() {
name.value='ls',
job.value.type="java工程师", //修改属性值 需要.value(因为是一个引用实现对象 基本数据类型使用的ref(数据劫持), 对象类型求助了vue内部的reactive函数(proxy)
job.value.salary="40k"
console.log(name);
}
return {
name,
job,
sayhi,
changeInfo,
};
},
4.reactive函数(对象类型数据)
import {reactive} from 'vue'
setup(){
// const 对象=reactive({}) 返回一个proxy的代理对象
let person =reactive({ //使用reactive函数可以使对象形式的数据变成响应式
name:'zs',
age:18,
job:{
type:'前端开发',
salary:"30k",
}
})
let hobby=reactive(['抽烟','喝酒','打麻将'])
function changeInfo(){
person.name='ls',
person.age=30,
person.job.type='后端开发',
person.job.salary='40k'
hobby[0]='学习'
}
return {
person, //返回一个代理对象(proxy代理的实例对象)
changeInfo
}
}
5.setup参数
props传参
<script>
export default{
props:['msg'],
setup(props){
console.log(props)
}
}
</script>
context参数
//父组件
<template>
<home @hello='showx' msg='你好' school='家里蹲大学'></home>
<template #qwe> //具名插槽 #qwe可以写成v-slot:qwe
<h3>你好啊哥哥们</h3>
</template>
</template>
<script>
import home from './components/home.vue'
export default {
components:{
home
},
setup(){
function showx(value){
console.log('99');
alert(`你好,你触发了hello事件,我收到的参数是${value}`)
}
return{
showx
}
}
};
</script>
//子组件
<template>
<button @click="handclick">测试触发一下父组件的hello事件</button>
<slot name="qwe"></slot> //具名插槽使用
</template>
<script>
export default{
props:['msg'],
emits:['hello'], //需要通知一下,否则会有警告(不影响使用)
setup(context){
console.log(context)
// context参数:attrs 获取当前组件上所有得属性得对象,props未声明得会到这里显示;slots;emit
// 触发父组件
function handclick() {
context.emit('hello',999)
}
return {
handclick,
};
}
}
</script>
6.computed计算属性
<template>
<div>
<h1>一个人的信息</h1>
姓:<input type="text" v-model="person.firstName">
<br>
名:<input type="text" v-model="person.lastName">
<br>
<span>全名:{{person.fullName}}</span>
</div>
</template>
<script>
import { reactive ,computed} from "vue"; //引入计算属性computed
export default {
name: "test",
// computed:{ //vue2写法(简写
// // 计算属性可以直接用
// fullName(){
// return this.person.firstName+'-'+this.person.lastName
// }
// },
setup() {
let person = reactive({
firstName: "张",
lastName: "三",
})
//计算属性--简写(未考虑可修改)
person.fullName=computed(()=>{
return person.firstName+'-'+person.lastName
})
//计算属性--完整写法(可读可改)
person.fullName=computed({
get(){
return person.firstName+'-'+person.lastName
}
set(value){
const nameArr=value.split('-')
person.firstName=nameArr[0]
person.lastName=nameArr[1]
}
})
return {
person,
//fullName
};
},
};
</script>
7.watch监听
//与vue2的watch配置功能一致
两个坑:
监听reactive的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)
监听reactive定义的响应式数据中某个属性时:deep配置有效
<template>
<h2>当前求和为:{{sum}}</h2>
<button @click="sum++">点我加1</button>
<h2>当前的信息为:{{msg}}</h2>
<button @click="msg+='!'">修改信息</button>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<button @click="person.name+='~'">修改信息</button>
<button @click="person.age++">修改信息</button>
</template>
<script>
//引入watch监听函数
import { ref,reactive,watch} from "vue";
export default {
setup() {
let sum=ref(0)
let msg=ref('你好啊')
let person=reactive({
name:'zs',
age:30
})
// 1.监视基本类型数据-多个
watch([sum,msg],(newVlaue,oldValue)=>{ //三个参数,第一个监听对象,第二个回调函数,第三个配置项如{immediate:true,deep:true} 可以在开始时候就监听
console.log('sum或msg变了',newVlaue,oldValue);
},{immediate:true})
// 2.监听基本类型数据-单个
watch(msg,(newVlaue,oldValue)=>{
console.log('msg变了',newVlaue,oldValue);
})
// 3.监听reactive所定义的对象类型数据
watch(person,(newVlaue,oldValue)=>{
console.log('person变了',newVlaue,oldValue);//oldValue值也变了,目前是vue3中的bug
})
// 4. 监视reactive所定义的一个响应式数据中的某个属性
watch(()=>person.age,(newVlaue,oldValue)=>{
console.log('person.age变化了',newVlaue,oldValue);
})
// 5.监视reactive所定义的一个响应式数据中的某些属性(推荐s函数表达式方式监听对象的值
watch([()=>person.age,()=>person.name],(newVlaue,oldValue)=>{
console.log('person.age或者name变化了',newVlaue,oldValue);
})
//特殊情况:监听reactive所定义的对象数据中的某个对象或者更深层的数据时
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person.job变化了',newValue,oldValue)
},{deep:true})//需要开启深度监听
// 返回一个对象(常用)
return {
sum,
msg,
person
}
},
};
</script>
8.watchEffect监听(一进来就触发)
<template>
<h2>当前求和为:{{ sum }}</h2>
<button @click="sum++">点我加1</button>
<h2>当前的信息为:{{ msg }}</h2>
<button @click="msg += '!'">修改信息</button>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>薪资:{{ person.job.j1.salary }}K</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { ref, reactive,watchEffect } from "vue";
export default {
setup() {
let sum = ref(0)
let msg = ref('你好啊')
let person = reactive({
name: '张三',
age: 19,
job: {
j1: {
salary: 30
}
}
})
//不指明监视哪个属性,监视的回调中用到哪个属性,就监视哪个属性
watchEffect(() => {
const x1 = sum.value //监视sum的值
const x2=person.job.j1.salary //监视salary
console.log('watchEffect监听了');
})
// 返回一个对象(常用)
return {
sum,
msg,
person
}
},
};
</script>
9.生命周期钩子函数
//两种方式:
第一种与vue2一样,作为配置项来写(beforeDestroy-->beforeUnmount destroyed-->unmounted)
第二种写在setup中(组合式api形式书写)
beforeCreate==>setup()
created==>setup()
其余的钩子全部带on前缀
写法: onMounted(()=>{})
10.hook
本质上是一个函数,把setup函数中使用得组合式api进行了封装
类似于vue2中得mixin
使用:
<template>
<h2>当前求和为:{{ sum }}</h2>
<button @click="sum++">点我加1</button>
<hr>
<h2>当前点击时鼠标得坐标为:x:{{point.x}} y:{{point.y}}</h2>
</template>
<script>
import { ref } from "vue";
import usePoint from '@/hooks/usePoint' //引入hooks中封装的函数
export default {
setup() {
let sum = ref(0);
let point =usePoint() //调用hooks中得函数
console.log(point);
// 返回一个对象(常用)
return {
sum,
point
};
},
};
</script>
//在src下创建hook文件夹 -》创建usePoint.js(封装hooks函数
import { reactive,onMounted,onBeforeUnmount } from "vue"
export default function savePoint() {
//实现鼠标“打点”相关得数据
let point = reactive({
x: 0,
y: 0
})
//实现鼠标“打点”相关得方法
function savePoint(e) {
console.log(e.pageX, e.pageY)
point.x = e.pageX
point.y = e.pageY
}
//实现鼠标“打点”相关得钩子
onMounted(() => {
window.addEventListener('click', savePoint)
})
onBeforeUnmount(() => {
window.removeEventListener('click', savePoint)
})
return point
}
11.toRef
<template>
<h3>{{name2}}</h3>
<h3>{{salary}}</h3>
<h2>姓名:{{ person.name }}</h2>
<h2>年龄:{{ person.age }}</h2>
<h2>薪资:{{ person.job.j1.salary }}K</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { reactive,toRef} from "vue";
export default {
setup() {
let person = reactive({
name: '张三',
age: 19,
job: {
j1: {
salary: 30
}
}
})
// 返回一个对象(常用)
return {
person,
name2:toRef(person,'name')//使用toRef指向person对象(类似于深拷贝
salary:toRef(person.job.j1,'salary')
}
}}
</script>
12.toRefs
<template>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>薪资:{{ job.j1.salary }}K</h2>
<button @click="person.name += '~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">增长薪资</button>
</template>
<script>
import { reactive,toRefs} from "vue";
export default {
setup() {
let person = reactive({
name: '张三',
age: 19,
job: {
j1: {
salary: 30
}
}
})
// 返回一个对象(常用)
return {
person,
...toRefs(person) //使用toRefs可以得到整个对象(类似于深拷贝数据
}
}}
</script>
13.Router路由跳转与传参
方式1
import { useRouter } from 'vue-router';
export default {
setup() {
const router = useRouter();
function goto(){
router.push("/about");
}
return{
goto //一定要要放在return里才能在模板上面使用
}
}
}
方式2
import router from "../../router/index.js";
router.push("/");
路由传参
import router from "../../router/index";
router.push({path:'/addShop',query:{id:id}})
//在其他页面获取这个传参
router.currentRoute._rawValue.query.id
14.在vuex中的用法
import { useStore } from 'vuex'
export default defineComponent({
setup() {
const store = useStore()
const count = store.state.count;
return {
count,
}
}
})
15.对于TypeScript的支持
//列表定义的数据
interface Applet {
id?: number;
code: string;
createAt: String,
logo: string,
merchantName: string,
name: string;
serviceName: string;
tag: string;
tagId: string;
}
const appletData = ref<Array<Applet>>([]);
//返回值 data中的值定义
interface AppletListResponse {
count: number;
list: Array<Applet>;
page: number | string;
pageSize: number | string;
}
//列表返回的值定义
interface AppletListRes {
code: number;
msg: string;
data: AppletListResponse;
}
appletList(params).then((res: AppletListRes) => {
if (res.code === 0) {
appletData.value = res.data.list;
total.value = res.data.count;
}
});
//参数
interface AppletParams {
page: number | string;
pageSize: number | string;
name?: string;
storeName?: string;
serviceName?: string;
tag?: string;
}
//接口请求
export const appletList = (params: AppletParams): Promise<AppletListRes> => {
return Http.get("/applet/list", params);
};
其他组合式api
1.shallowReactive与shallowRef
shalolowReactive 只考虑对象的第一层数据(浅响应式)
shallowRef 只能处理基本类型数据响应式
2.readyonly与shallowReadyonly
//禁止修改数据
readyonly(深只读) shallowReadyonly(浅只读)
<template>
<h1>{{sum}}</h1>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
<h2>薪资:{{ job.j1.salary }}K</h2>
<button @click="sum++">sum++</button>
<button @click="name += '~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">增长薪资</button>
</template>
<script>
import {ref, reactive,toRefs,readonly,shallowReadonly} from "vue";
export default {
setup() {
let sum=ref(0)
let person = reactive({
name: '张三',
age: 19,
job: {
j1: {
salary: 30
}
}
})
// person=readonly(person)
person=shallowReadonly(person)
// sum=readonly(sum)
sum=shallowReadonly(sum)
// 返回一个对象(常用)
return {
sum,
...toRefs(person)
}
}
}
</script>
应用场景:接收别人组件传过来的值,使用readyonly进行保护,操作结果来的值不会影响别人页面
3.toRaw与markRaw
toRaw将reactive生成的响应式数据对象还原成普通对象
使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的操作不会引起页面更新
markRaw:标记一个对象,使其永远不会再成为响应式对象(常用)
应用场景:1.有些之不应被设置为响应式的,例如复杂的第三方类库等
2.当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
4.provide与inject
使用:
//祖组件
let car=reactive({
name:'奔驰',
price:'40w'
})
provide('car',car)
//后代组件
let car= inject("car");
return{car}//记得需要return出去
响应式数据判断
isRef:检查一个值是否为一个ref对象
isReactive:检查一个对象是否由reactive创建的响应式代理
isReadonly:检查一个对象是否由readyonly创建的只读代理
isPoxy:检查一个对象是否由reactive或者readonly方法创建的代理
Teleport(传送) 重点!!
传送,可以打破多级组件,直接定位到目标结构
<teleport to="移动位置"> // 将该结构直接移动到对应得结构中,比如body,htl等
<div v-if="isShow" class="mask">
<div class="dialog">
<h3>我是一个弹窗</h3>
</div>
</div>
</teleport>
Suspense与异步组件
Suspense :等待异步组件时渲染一些额外的内容,增强用户体验
//异步引入组件
<template>
<div class="son">
<h1>son</h1>
<Suspense> //使用Suspense包裹组件,并配置好default和fallback
<template v-slot:default>//在该插槽中使用组件
<Child></Child>
</template>
<template v-slot:fallback>//组件加载前的结构
<h3>加载中</h3>
</template>
</Suspense>
</div>
</template>
<script>
import {defineAsyncComponent} from 'vue'
const Child =defineAsyncComponent(()=>import('./components/child.vue'))
</script>
vue3与vue2区别
1. 根组件挂载(入口文件main.js)
//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import {createApp} from 'vue'
import App from './App.vue'
//创建应用实例对象----app(类似于之前的vue2中的vm,但app比vm更'轻'
const app = createApp(App)
//挂载
app.mount('#app')
/*
//vue2挂载方法
const vm= new Vue({
render:h=>h(App)
})
vm.$mount('#app')*/
2. vue3组件中模板结构可以没有根标签
3.1 vue2数据响应式原理
<html>
...
<body>
<script>
let person={
name:"zs",
age:18
}
//模拟Vue2中实现响应式
let p={}
//正常是需要循环遍历key的
Object.defineProperty(p,'age',{ //数据劫持
configurable:true //可配置的
get(){
return person.age
},
set(value){
console.log('有人修改了age属性,我发现了,我要去更新页面了')
person.age=value
}
})
</script>
</body>
</html>
3.2 vue3数据响应式原理
通过Proxy(代理):拦截对象中任意属性的变化,增删改查
通过Reflect(反射):对(源对象)被代理对象的属性进行操作
<html>
...
<body>
<script>
let person={
name:"zs",
age:18
}
//模拟Vue3中实现响应式 基于Es6的proxy代理
const p=new Proxy(person,{
//有人读取p的某个属性时调用
get(target,propName){
console.log(`有人读取了p身上的${propName}属性`)
//return target[propName]
return Reflect.get(target,propName) //reflect反射对象
},
//有人修改p的某个属性、或给p追加某个属性时调用
set(target,propName,value){
console.log(`有人修改了p身上的${propName}属性,我要去需修改界面了`)
// target[propName]=value
return Reflect.set(target,propName,value)
},
//有人删除p的某个属性时调用
deleteProperty(target,propName){
console.log(`有人删除了p身上的${propName}属性,我要去需修改界面了`)
//return delete taraget[propName]
return Reflect.deleteProperty(target,propName)
}
})
</script>
</body>
</html>
Vue3全局api
2.x全局api(Vue) 3.x实例api(app)
vue.config.xxx -----> app.config.xxxx
Vue.config.productionTip //vue3中移除
Vue.component -----> app.component
Vue.directive -----> app.directive
Vue.mixin -----> app.mixin
Vue.use -----> app.use
Vue.prototype -----> app.config.globalProperties
1.移除了keyCode作为v-on的修饰符,同时也不再支持config.keyCodes
2.移除了v-on.native修饰符
父组件中绑定事件
<my-component v-on:close="handleClose" v-on:Click="handleClick" />
子组件中声明自定义事件
<script>
export default{
emits:['close']
}
</script>
3.移除了filter过滤器 (官方推荐使用computed与methods来使用函数处理)
示例:
第一种用computed实现
<template>
<div id="app">
<ul v-for="(item, index) in arr" :key="index">
<li>快递公司:{{ item.deliverCompany }}</li>
<!-- 使用计算属性 -->
<li>运输状态:{{ computedText(item.expressState) }}</li>
</ul>
</div>
</template>
<script>
export default {
// data ...... 篇幅有限直接省略掉
computed: {
computedText() {
// 计算属性要return一个函数接收参数
return function (state) {
switch (state) {
case "1":
return "待发货";
break;
case "2":
return "已发货";
break;
case "3":
return "运输中";
break;
case "4":
return "派件中";
break;
case "5":
return "已收货";
break;
default:
return "快递信息丢失";
break;
}
};
},
},
};
</script>
第二种使用methods实现
<template>
<div id="app">
<ul v-for="(item, index) in arr" :key="index">
<li>快递公司:{{ item.deliverCompany }}</li>
<!-- 使用方法 -->
<li>运输状态:{{ methodsText(item.expressState) }}</li>
</ul>
</div>
</template>
<script>
export default {
// data ...... 篇幅有限直接省略掉
methods: {
methodsText(state) {
switch (state) {
case "1":
return "待发货";
break;
case "2":
return "已发货";
break;
case "3":
return "运输中";
break;
case "4":
return "派件中";
break;
case "5":
return "已收货";
break;
default:
return "快递信息丢失";
break;
}
},
},
};
</script>
Vue3挂载全局axios
第一种方案
//在main.js中写入
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
const app = createApp(App)
app.config.globalProperties.$http = axios//全局挂载
//组件中使用
vue3.0中是没有this的。使用getCurrentInstance来获取上下文
//getCurrentInstance() 获取全局globalProperties 中配置的信息
const { proxy } = getCurrentInstance()// 这里的proxy相当于this
proxy.$http.get('api/getNewsList')
.then((response)=>{
console.log(response)
})
第二种方案
二、使用vue-axios插件
//首先在主入口文件main.js中引用:
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
app.use(VueAxios,axios);
//然后在组件中引用,注意vue3.x没有this
axios.get('api/getNewsList')
.then((response)=>{
console.log(response)
})
工具库简单使用
mock.js模拟数据
安装
npm i mockjs
使用
import Mock from 'mockjs'
示例:
// 使用 Mock
1.直接定义数据
let dataSource = Mock.mock({
'dataSource|5':[{
'key|+1': 1,
'mockTitle|1':['哑巴', 'Butter-fly', '肆无忌惮', '摩天大楼', '初学者'],
'mockContent|1': ['你翻译不了我的声响', '数码宝贝主题曲', '摩天大楼太稀有', '像海浪撞破了山丘'],
'mockAction|1': ['下载', '试听', '喜欢']
}]
})
// 输出结果
console.log(dataSource);
2.模拟接口返回数据:
//第一步:在assets中创建mock.js
import Mock from 'mockjs'
Mock.mock('/meun', /post|get/i, {
// /post|get/i 匹配post和get模式 也可以用'post'或'get'
"ret":0,
"data":
{
"mtime": "@datetime",//随机生成日期时间
"score|1-800": 800,//随机生成1-800的数字
"rank|1-100": 100,//随机生成1-100的数字
"stars|1-5": 5,//随机生成1-5的数字
"nickname": "@cname",//随机生成中文名字
}
})
//第二步在main.js中引入
import './assets/mock'
//第三步使用接口
import axios from 'axios'
axios({
method:'get',
url:'/meun'
}).then((res)=>{
console.log(res);
})
数据模板定义规范:
三部分构成:属性名(name)、生成规则(rule)、属性值(value)
'name|rule':value
配置请求代理解决跨域
根目录下创建vite.config.js
module.exports= {
proxy: {
// 选项写法
'/api': {
target: 'https://pvp.qq.com/', //此处为需要处理跨域的接口
changeOrigin: true, //需要配置
rewrite: (path) => path.replace(/^\/api/, '')//重写地址
},
}
}
vue3使用script setup 语法糖
<script setup>
import {ref} from 'vue'
import MyComponent from './MyComponent.vue' //无需注册声明(注:导入需要加上.vue后缀,否则ts无法识别)
const msg =ref("HELLO")
const fn=()=>{
console.log(msg)
}
//在<script setup>中必须使用defineProps与defineEmits来声明props和 emits
const props=defineProps({
foo:String,
default:()=>{return '测试信息'} //默认值
})
const emit = defineEmits(['change','delete'])
//1.与普通的<script>比较,如果在组件内部使用,无需return
//2.如果需要暴露给外部使用,需要使用:dinfineExpose
defineExpose({
msg,
fn
})
</script>
<template>
//可以直接在模板中使用
<div @click="fn">{{msg}}</div>
<MyComponent></MyComponent>// 可以直接在模板中使用定义的组件
</template>
pinia 状态管理
安装
npm i pinia@next
//src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
// 实例化 Vue
const app = createApp(App)
// 安装 Pinia
app.use(createPinia())
// 挂载在真实 DOM
app.mount('#app')
----------------------------------------------------------
//若在vue2中使用 需要额外安装PiniaVuePlugin
import { createPinia, PiniaVuePlugin } from 'pinia'
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
new Vue({
el: '#app',
pinia,
})
示例
//src/store/modules/counter.ts
import {defineStore} from "pinia"
//使用前必须用difineStore()定义一个仓库
//方式一:
export const useCounterStore = defineStore("counter",{
state:()=>{
return {
count:0
}
},
actions:{
increment(){
this.count++
}
}
})
//方式二:使用类似setup()方式定义store
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
<template>
<div>count:{{counter.count}}</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from "pinia";
//导入store
import { useCounterStore } from '@store/modules/counter';
const counter = useCounterStore();//接收store数据
// const {count}=counter // 注意: 直接解构会使变量失去响应式
const {count}=storeToRefs(counter)
//方式一:修改单一数据
counter.count++
//f修改多个数据 $patch批量更新
counter.$patch({count:counter.count+1})
// 方式三: $patch 一个函数,批量更新 (建议使用方式)
// 这里传了一个函数
// mainStore.$patch(state=>{
// state.count++
// })
counter.increment()
</script>