crm开发定制vue-cli 创建vue3项目

文章目录

一、环境准备

前提:

# 安装node环境node -vnpm -v# crm开发定制卸载旧脚手架工具npm uninstall vue-cli -goryarn global remove vue-cli# crm开发定制安装新版的脚手架工具 指定版本@vue/cli@版本号npm install -g @vue/cli
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

创建项目

vue create vue3
  • 1








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模式 crm开发定制默认历史模式? 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. crm开发定制格式化配置祖安泽标准? 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. crm开发定制不保存为模板,crm开发定制立即创建项目? Save this as a preset for future projects? (y/N) n
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
二、核心组件
2.1.

安装 axios
使用axios发送ajax请求

npm install axios --save
  • 1

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)    })  })}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

后续更新集成请求拦截和响应拦截+模块单独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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

大家可以直接使用我的调用测试地址,自己的地址会有跨域问题

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: {},});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

后期,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封装异步代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

传统方式使用

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: {},});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

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: {},});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
2.3.
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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
<template>  <router-view /></template><script>export default {  name: 'App',}</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

参数传递

,{    path: '/shop/:id',    name: 'Shop',    component: () => import(/* webpackChunkName: "shop" */ '../views/shop/Shop')  }
  • 1
  • 2
  • 3
  • 4
  • 5

参数接收

<template>  <div class="wrapper">    <div class="title">      <div        class="iconfont title__back"        @click="handleBackClick"      >&#xe6f2;</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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发