文章目录
- 一、环境准备
- 二、核心组件
- 2.1. axios封装
- 2.2. vuex
- 2.3. vue-router
一、环境准备
前提:
# 安装node环境
node -v
npm -v# 卸载旧脚手架工具
npm uninstall vue-cli -g
or
yarn global remove vue-cli# 安装新版的脚手架工具 指定版本@vue/cli@版本号
npm install -g @vue/cli
创建项目
vue create vue3
Vue CLI v4.5.14
┌─────────────────────────────────────────────┐
│ │
│ New version available 4.5.14 → 4.5.15 │
│ Run yarn global add @vue/cli to update! │
│ │
└─────────────────────────────────────────────┘
// 1.手工模式
? Please pick a preset: Manually select features
// 2.安装 Router, Vuex, CSS 插件
? Check the features needed for your project: Choose Vue version, Babel, Router, Vuex, CSS Pre-processors, Linter
// 3. vue3.x版本
? Choose a version of Vue.js that you want to start the project with 3.x
// 4. 选择hash模式 默认历史模式
? Use history mode for router? (Requires proper server setup for index fallback in production) No
// 5. 选择css插件Sass/SCSS
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)
// 6. 格式化配置祖安泽标准
? Pick a linter / formatter config: Standard
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
// 7. 不保存为模板,立即创建项目
? Save this as a preset for future projects? (y/N) n
二、核心组件
2.1. axios封装
安装 axios
使用axios发送ajax请求
npm install axios --save
utils/request.js
import axios from 'axios'const instance = axios.create({baseURL: 'https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd',timeout: 10000
})export const get = (url, params = {}) => {return new Promise((resolve, reject) => {instance.get(url, { params }).then((response) => {resolve(response.data)}, err => {reject(err)})})
}export const post = (url, data = {}) => {return new Promise((resolve, reject) => {instance.post(url, data, {headers: {'Content-Type': 'application/json'}}).then((response) => {resolve(response.data)}, err => {reject(err)})})
}
后续更新集成请求拦截和响应拦截+模块单独api
案例:获取博文发布作者姓名
<template><div class="about"><h1 @click="handleClick">This is an about page</h1><button @click="getBlogData">获取博文数据</button></div><div>{{ name }}</div>
</template>
<script>
import { toRefs } from 'vue';
import { useStore } from 'vuex';
export default {name: 'about',setup() {const store = useStore();// 从store.state把name解构出来const { name } = toRefs(store.state);const handleClick = () => {// 异步修改数据store.dispatch('getData', 'hello aync');// 同步修改数据// store.commit('changeName', 'hello2');};const getBlogData = () => {store.dispatch('getBlogData');};return { name, handleClick, getBlogData };},
};
</script>
大家可以直接使用我的调用测试地址,自己的地址会有跨域问题
import { createStore } from 'vuex';
import axios from 'axios';
// VueX 数据管理框架
// VueX 创建一个全局唯一的仓库,用来全局的数据
export default createStore({state: {name: 'dell',},mutations: {changeName(state, val) {state.name = val;},},actions: {// 异步逻辑getBlogData(store) {axios.get('https://www.fastmock.site/mock/a4701044176a98816d53ce26897cdd3b/api/hxq').then((res) => {console.log(res);const name = res.data.name;store.commit('changeName', name);});},// 修改名字getData(store, val) {setTimeout(() => {store.commit('changeName', val);}, 2000);},},modules: {},
});
后期,api接口具体调用会api目录下的模块具体的xx.js中,然后在,store的index模块的actions下面调用此方法即可
2.2. vuex
store/index.js
VueX 数据管理框架
VueX 创建一个全局唯一的仓库,用来全局的数据,一处修改,全局立即生效
数据声明和数据获取使用:数据放到state里面
通过计算属性获取到数据
computed: {myName() {return this.$store.state.name;}}数据修改
声明一个事件
触发一个/*** 1.dispatch方法,派发一个action,名字叫做change* 2.vuex中actions就会感知到change 这个action,执行store中actions下面change的方法(在actions中的方法不能直接修改数据,必须通过提交一个commit发送请求)* 3.在actions下面change的方法内部,提交一个commit 叫做change的数据改变方法* 4.mutation 感知到提交的mutation改变,执行change方法,改变数据* 5.*/state中的数据只能在mutations中去修改mutation只执行同步的代码逻辑actions中写异步的逻辑(不做数据修改具体操作,只是发送commit请求)如果不需要异步操作:也可以this.$store.commit('change', 'hello word');mutations下的change方法也会感知到,直接修改数据dispatch是和actions做关联的commit是和mutations做关联的一般 mutations中封装同步代码actions封装异步代码
传统方式使用
import { createStore } from 'vuex';
// VueX 数据管理框架
// VueX 创建一个全局唯一的仓库,用来全局的数据
export default createStore({state: {name: 'dell',},mutations: {// 第4步,对应的mutation 被执行change(state, val) {// 第5步,在mutation里面修改数据state.name = val;},},actions: {// 第2步,store感知到你触发一个change的action,执行change方法change(store, val) {// 第3步,提交一个commit 触发一个mutationsetTimeout(() => {store.commit('change', val);}, 2000);},},modules: {},
});
about.vue
<template><div class="about"><h1 @click="handleClick">This is an about page</h1><div>{{ myName }}</div></div>
</template>
<script>
export default {name: 'about',computed: {myName() {return this.$store.state.name;},},methods: {handleClick() {/*** 1.dispatch方法,派发一个action,名字叫做change* 2.感知change 这个action,执行store中actions下面change的方法* 3.commit 提交一个叫做change的数据改变* 4.mutation 感知到提交的mutation改变,执行change方法,改变数据* 5.*/this.$store.commit('change', 'hello word');// this.$store.dispatch('change', 'hello word');},},
};
</script>
compositionAPI方式
从vuex中引入useStore函数,获取全局数据对象
然后通过useStore获取Store,使用commit调用同步方法改数据
使用dispatch调用异步方法改数据
import { createStore } from 'vuex';
// VueX 数据管理框架
// VueX 创建一个全局唯一的仓库,用来全局的数据
export default createStore({state: {name: 'dell',},mutations: {changeName(state, val) {console.log;val;state.name = val;},},actions: {// 异步逻辑getData(store, val) {setTimeout(() => {store.commit('changeName', val);}, 2000);},},modules: {},
});
about.vue
<template><div class="about"><h1 @click="handleClick">This is an about page</h1></div><div>{{ name }}</div>
</template>
<script>
import { toRefs } from 'vue';
import { useStore } from 'vuex';
export default {name: 'about',setup() {const store = useStore();// 从store.state把name解构出来const { name } = toRefs(store.state);const handleClick = () => {// 异步修改数据store.dispatch('getData', 'hello aync');// 同步修改数据// store.commit('changeName', 'hello2');};return { name, handleClick };},
};
</script>
2.3. vue-router
import { createRouter, createWebHashHistory } from 'vue-router'const routes = [{path: '/',name: 'Home',component: () => import(/* webpackChunkName: "home" */ '../views/home/Home')},{path: '/cartList',name: 'CartList',component: () => import(/* webpackChunkName: "cartList" */ '../views/cartList/CartList')},{path: '/orderConfirmation/:id/:addressId?',name: 'OrderConfirmation',component: () => import(/* webpackChunkName: "orderConfirmation" */ '../views/orderConfirmation/OrderConfirmation')}, {path: '/orderList',name: 'OrderList',component: () => import(/* webpackChunkName: "orderList" */ '../views/orderList/OrderList')},{path: '/shop/:id',name: 'Shop',component: () => import(/* webpackChunkName: "shop" */ '../views/shop/Shop')}, {path: '/register',name: 'Register',component: () => import(/* webpackChunkName: "register" */ '../views/register/Register'),beforeEnter(to, from, next) {const { isLogin } = localStorage;isLogin ? next({ name: 'Home'}): next();}}, {path: '/login',name: 'Login',component: () => import(/* webpackChunkName: "login" */ '../views/login/Login'),beforeEnter(to, from, next) {const { isLogin } = localStorage;isLogin ? next({ name: 'Home'}): next();}}, {path: '/chooseAddressList/:shopId',name: 'ChooseAddressList',component: () => import(/* webpackChunkName: "chooseAddressList" */ '../views/chooseAddressList/ChooseAddressList'),},{path: '/myAddressList',name: 'MyAddressList',component: () => import(/* webpackChunkName: "myAddressList" */ '../views/myAddressList/MyAddressList'),}, {path: '/upsertAddress/:id?',name: 'UpsertAddress',component: () => import(/* webpackChunkName: "upsertAddress" */ '../views/upsertAddress/UpsertAddress'),}, {path: '/person',name: 'PersonalInfo',component: () => import(/* webpackChunkName: "person" */ '../views/personalInfo/PersonalInfo'),}
]const router = createRouter({history: createWebHashHistory(),routes
})router.beforeEach((to, from ,next) => {const { isLogin } = localStorage;const { name } = to;const isLoginOrRegister = (name === "Login" || name === "Register");(isLogin || isLoginOrRegister) ? next() : next({ name: 'Login'});
})export default router
<template><router-view />
</template><script>
export default {name: 'App',
}
</script>
参数传递
,{path: '/shop/:id',name: 'Shop',component: () => import(/* webpackChunkName: "shop" */ '../views/shop/Shop')}
参数接收
<template><div class="wrapper"><div class="title"><divclass="iconfont title__back"@click="handleBackClick"></div><div class="title__text">管理收货地址</div><div class="title__add" @click="handleAddClick">新建</div></div><Addressv-for="address in addressList":key="address._id":address="address"@click="() => handleUpdateClick(address._id)"/></div>
</template><script>
import Address from '../../components/Address'
import useCommonAddressEffect from '../../effects/addressEffect'import { toRefs } from 'vue'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'export default {name: 'MyAddressList',components: { Address },setup() {const store = useStore()const router = useRouter()const { addressList } = toRefs(store.state)const { getAddressList } = useCommonAddressEffect()getAddressList(true)const handleBackClick = () => { router.back() }const handleAddClick = () => { router.push({ name: 'UpsertAddress'}) }const handleUpdateClick = (addressId)=> {router.push(`/upsertAddress/${addressId}`)}return { addressList, handleBackClick, handleAddClick, handleUpdateClick }}
}
</script><style lang="scss" scoped></style>