基于Vue3.0创建基本项目架构;

从零开始使用Vue3.0创建项目

一、Vue3.0 官网地址及NPM源:

Vue3.0官方网站
国内NPM源

二、从零开始创建一个HelloWorld项目;

2.1 npm安装最新稳定版Vue:

最新稳定版

npm install vue@next

2.2 npm安装最新稳定版Vue-Cli:

yarn global add @vue/cli

	npm install -g @vue/cli

2.3 更新相关插件到对应的版本:

	vue upgrade --next

2.4 创建空项目:

名字要全部小写:大写报错 Warning: name can no longer contain capital letters

vue create  <项目文件夹名称>

在这里插入图片描述

这里直接选择的第二项:Vue 3;
第三项是 手动选择设置;

见上图代表创建 空白项目成功;


三、引入Vue-router4.0新版路由


3.1 NPM安装新版路由

npm install --save vue-router@next

package.json文件内:下图代表安装完成在这里插入图片描述-------

3.2 Vue实例配置引入路由

创建如图文件:配置涉及的相关文件如下
router/index.js
main.js
App.vue

HelloWorld.vue
python.vue

在这里插入图片描述


3.2.1 创建router实例:

	router/index.js文件[ 生成路由实例 ]
import { createRouter, createWebHistory } from 'vue-router';
const routes = [
    { path: '/', redirect: '/user' },
    {
        path: '/user', component: () => import('@/components/HelloWorld.vue'), children: [
            // 子路由路径开头不带斜杠/
            { path: 'money', component: () => import('@/components/python.vue') }
        ]
    }
]

// createRouter替换旧版的new Router()
const router = createRouter({
    history: createWebHistory(),
    routes
})

export default router;

3.2.2 项目入口文件main.js中引入router实例

	main.js中引入 3.2.1中router/index.js中创建的router实例
	main.js相关内容:
import { createApp } from 'vue'
import App from './App.vue'

// 引入router
import router from './router'
var app = createApp(App);
// 应用router
app.use(router);
app.mount('#app')

3.2.3 配置路由地址对应组件页面显示位置 [ router-view标签 ]

	项目 App.vue 根组件:
	配置router-view标签,承载路由对应的组件内容;
	App.vue  文件内容 :[ 根组件 ]
<template>
<div>我是蓝色,在我之下,展示一级路由地址的对应组件内容</div>
<!-- 一级路由组件装载位置 -->
  <router-view></router-view>
</template>

<script>

export default {
  name: 'App'
}
</script>

<style>
#app{
  background: skyblue;
  padding: 30px;
}
</style>



	HelloWorld.vue内容:[ 一级路由对应组件 ]
<template>
  <div class="hello">
    <div>--router-view--</div>
    我是绿色,我是一级路由地址的组件内容; 在我之下是二级路由地址装载的组件位置;
    <!-- 二级路由组件装载位置 -->
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
  background: green;
  padding: 20px;
}
</style>


	python.vue内容: [ 二级路由对应组件 ]
<template>
  <div class="hello">
    <div>--router-view--</div>
    我是红色
    我是装载进来的二级路由组件
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello{
  background: red;
  padding: 20px;
}
</style>

四、引入Vue3.0 Vuex

4.1 组成及基础功能了解;

4.1.1 组成及经典关系图

	组成:
	一、State
	二、Getters
	三、Mutations
	四、Actions
	五、Modules
	六、vuex-persistedstate  [ 刷新页面,项目重新加载,vuex 会重置,所有状态回到初始状态,使用 vuex-persistedstate 
		可以避免这种情况 ]

	经典关系图:
	    1. Components[ 页面 ] 
	--> 2. Dispatch 触发Actions中的方法 	   
	--> 3. 被触发的Action方法内部Commit触发Mutations去直接更改State状态 
	--> 4. State状态变更影响Render渲染 
	--> 5. Components [ 页面 ] 刷新

请添加图片描述

4.1.2 State

import { computed } from 'vue'
import { useStore } from 'vuex'
export default {
  setup () {
    const store = useStore()
    return {
      count: computed(() => store.state.count)
    }
  }
}

4.1.3 Getters

import { computed } from 'vue'
import { useStore } from 'vuex'
export default {
  setup () {
    const store = useStore()
    return {
      double: computed(() => store.getters.double)
    }
  }
}

4.1.4 Mutations

4.1.4.1 注意点简介
	Mutation 必须是同步函数

	1. 直接更改 Vuex 的 Store 中的状态的【唯一方法】是 mutation中;
	2. 默认接受 state 作为第一个参数
	3. 不能直接调用一个 mutation 处理函数;
	4. 必须 store.commit('increment') 调用
	5. store.commit('increment', {amount: 10}) :可传入额外的参数 ;额外参数应该是一个对象,这样可以包含多个字段
	, 并且记录的 mutation 会更易读 ;
4.1.4.2 每个 mutation 都 2 个组成部分
每个 mutation 都 2 个组成部分:
1.一个字符串的事件类型 (type) 
2.一个回调函数 (handler)
mutations: {
  increment (state, payload) { // 'increment '就是一个字符串的事件类型 (type);
    state.count += payload.amount // 更改state的函数体:一个回调函数 (handler)
  }
}
4.1.4.3 常量替代 Mutation 事件类型
	创建单独文件放置这些Mutation常量:
	作用:归纳所有更改state的Mutation,多人协作的大型项目中,这会很有帮助;
// mutation-types.js 单独文件
export const SOME_MUTATION = 'SOME_MUTATION'
	store.js文件对应变更:
// store.js
import { createStore } from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = createStore({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) { // SOME_MUTATION位置是一个字符串的事件类型 (type)
      // 修改 state
    }
  }
})
4.1.4.4 组件中提交 Mutation
	1. this.$store.commit('xxx') ;
	2. 使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)
import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`

      // `mapMutations` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
    })
  }
}

4.1.5 Action

4.1.5.1 注意点简介
	Action 提交的是 mutation,【 不能 】直接变更状态;
	Action 可以包含任意【 异步 】操作;
4.1.5.2 代码示例:
	参数: 一个与 store 实例具有相同方法和属性的 context 对象;
const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})
	 ES2015 的参数解构来简化代码;
actions: {
  increment ({ commit }) {
    commit('increment')
  }
}
4.1.5.3 分发 Action[ 触发Action ]:
	store.dispatch('increment')方法触发;

额外参数:[ 第二参数 ]   类似 Mutation
// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})
4.1.5.4 组件中分发 Action[ 触发Action ]:
	this.$store.dispatch('xxx');
	mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):
import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}
4.1.5.5 组合 Action:
	1. store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise
	2. store.dispatch 仍旧返回 Promise:
actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

store.dispatch('actionA').then(() => {
  // ...
})
	另外一个 action 中也可以:
actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}
	利用 async / await,我们可以如下组合 action:
	// 假设 getData() 和 getOtherData() 返回的是 Promise
// 假设 getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}

4.1.6 Module

待补充

4.2 简单实例:创建一个基础Store;

4.2.1 基本目录结构

	store
├── index.js          # 我们组装模块并导出 store 的地方
├── actions.js        # 根级别的 action
├── mutations.js      # 根级别的 mutation
└── modules
    ├── cart.js       # 购物车模块
    └── products.js   # 产品模块

4.2.2 相关文件内容

4.2.2.1 index.js ,创建store实例
	index.js文件:创建store实例
import { createStore, createLogger } from 'vuex'
import cart from './modules/cart'
import products from './modules/products'

const debug = process.env.NODE_ENV !== 'production'

export default createStore({
  modules: {
    cart,
    products
  },
  strict: debug,
  plugins: debug ? [createLogger()] : []
})
4.2.2.2 使用modules模块化管理store
	modules/cart.js
// 接口
import shop from '../../api/shop'

// state
const state = () => ({
    name: '矿泉水',
    number: 2,
    successful: ''
})
// getters
const getters = {
    cartProducts: (state, getters, rootState) => {
        return {
            name: state.name
        }
    },
    cartTotalPrice: (state, getters) => {
        return getters['cartProducts'].name + state.number;
    }
}
// actions
const actions = {
    async checkout({ commit, state }, products) {
        try {
            // 请求数据
            await shop.buyProducts(products)
            // 获取数据后commit触发Mutation更改或保存一些需要的state
            commit('setCheckoutStatus', 'successful')
        } catch (e) {
            // 请求失败\报错处理;
            console.error(e)
            commit('setCheckoutStatus', 'failed')
        }
    }
}

// mutations
const mutations = {
    setCheckoutStatus(state, isOK) {
        state.successful = isOK;
    }
}
export default {
    state,
    getters,
    actions,
    mutations
}


4.2.2.3 项目入口文件引入store实例
	入口文件main.js 引入store实例
import { createApp } from 'vue'
import App from './components/App.vue'
import store from './store'

const app = createApp(App)

app.use(store)

app.mount('#app')

五、axios 封装:搭建Http请求API接口文件;

5.1 NPM安装

	npm install axios --save

5.2 创建axios实例

	tool/request.js
import axios from 'axios'

// 创建axios
const service = axios.create({
  baseURL: '你的请求前缀/api'timeout:5000
});

// 添加请求拦截器
service.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  // 做一些统一的处理
  // 对于一些特别的请求拦截
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
service.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  console.log('res',response);
  return response;
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error);
});

export default service;

5.3 业务api.js中载入axios封装实例

	例如: userApi.js
import service from "../tool/request"

// get获取,无参数
export function getSeller(){
// 返回一个Promise对象
  return service.request({
    method:'get',
    url:'/seller'
  })
}
// get获取,有参数
export function getParams(params){
// 返回一个Promise对象
  return service.request({
    method:'get',
    url:'/seller',
    params
  })
}

// get删除,拼接
export function del(id){
// 返回一个Promise对象
  return service.request({
    method:'get',
    url:'/seller' + id
  })
}
// post的默认传参方式data
export function updateData(data){
// 返回一个Promise对象
  return service.request({
    method:'post',
    url:'/seller',
    data
  })
}
// post的params传参方式
export function updateParams(params){
// 返回一个Promise对象
  return service.request({
    method:'post',
    url:'/seller',
    params
  })
}

5.4 组件中调用接口

	组件中调用userApi.js接口文件中的接口;
...
import {getSeller} from '../api/userApi.js'
...

async getData(){
	// getSeller是一个Promise对象
      const {data:res} = await getSeller()
      this.allData = res
      // 数据从小到大排序
      this.allData.sort((a,b)=>{
        return a.value - b.value
      })
    },

六 、Vue-Cli 环境变量文件: [ .env ]

6.1 项目根目录中放置 .env

	项目根目录中放置下列文件来指定环境变量:
	
	.env                # 在所有的环境中被载入
	.env.local          # 在所有的环境中被载入,但会被 git 忽略
	.env.[mode]         # 只在指定的模式中被载入
	.env.[mode].local   # 只在指定的模式中被载入,但会被 git 忽略; 只在本地有效的变量  .local

6.2 .env 文件内部变量定义规则

	仅识别 三 种规格变量;
	1. NODE_ENV
	2. BASE_URL
	3. 以 VUE_APP_ 开头的自定义变量 ;示例:第七大节7.1中配置反向代理中的 VUE_APP_LOGIN_API ;

	.env.development 简例:
# 开发环境配置
ENV = 'development'

# Golf系统
VUE_APP_BASE_API = '/dev-api'
# request.js 封装的axios的Http请求实例 启用了baseURL,
# 那么所有的api.js中定义的业务接口url,实际发起请求时都在此url基础上加了一层前缀 '/dev-api'
# 所以下方 VUE_APP_LOGIN_API /dev-api/login-api 写法只是为了拼凑在反向代理中匹配到此特殊路径标识时,执行反向代理;
# 上述场景应用在 一个项目中需要代理多个不同跨域;
VUE_APP_LOGIN_API = '/dev-api/login-api'

# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true


	变量访问:
	console.log(process.env.VUE_APP_LOGIN_API )

七 、Vue3.0 手动创建配置文件 vue.config.js

7.1 配置本地跨域反向代理

7.1.1 项目中相关数据搜集、梳理


	业务接口api.js文件:
	
	此处假设tool/request.js文件中axios封装实例已经开启baseURL属性赋值:
	const service = axios.create({
	    baseURL: process.env.VUE_APP_BASE_API,
	    // timeout: 5000,
	});
	
	开启baseURL代表意义:
	实际http请求在业务api接口的url基础上加上一层前缀;
	业务地址:url:'/login-api/seller' ;
	实际请求地址:process.env.VUE_APP_BASE_API + '/login-api/seller' ;
import service from "../tool/request"

// get获取,无参数
export function getSeller(){
// 返回一个Promise对象
  return service.request({
    method:'get',
    url:'/login-api/seller'
  })
}

7.1.2 开始配置反向代理

	vue.config.js 文件内: proxy属性;
proxy: {
	[process.env.VUE_APP_LOGIN_API ]: {
        target: `http://www.baidu.com/api/shop`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_LOGIN_API ]: ''
        }
      }
}

	上述 代码分析:
	第六节:6.2小节 .env.development 简例:获取环境变量 process.env.VUE_APP_LOGIN_API 结果为 '/dev-api/login-api';
	
	1. 发起Http请求,检测请求路径中是否匹配 [ process.env.VUE_APP_LOGIN_API  ],即 '/dev-api/login-api';
	2. 如果匹配到,那么将路径'/dev-api/login-api' 左侧替换为 target属性的值:`http://www.baidu.com/api/shop` ,
	即要跨的域;
	3. pathRewrite :替换路径中的  '/dev-api/login-api' 为空;
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值