vue-cli 创建vue3项目
文章目录一、环境准备二、核心组件2.1. axios封装2.2. vuex2.3. vue-router一、环境准备前提:# 安装node环境node -vnpm -v# 安装镜像源工具npm install nrm -gnrm ls# 使用淘宝镜像源nrm use taobaonrm ls# 卸载旧脚手架工具npm uninstall vue-cli -goryarn global remove
·
一、环境准备
前提:
# 安装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 触发一个mutation
setTimeout(() => {
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">
<div
class="iconfont title__back"
@click="handleBackClick"
></div>
<div class="title__text">管理收货地址</div>
<div class="title__add" @click="handleAddClick">新建</div>
</div>
<Address
v-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>
更多推荐
已为社区贡献25条内容
所有评论(0)