В прошлой статье писал про интеграцию vue и typescript, и обнаружил, что многие мелкие партнеры очень заинтересованы в проектах, построенных с помощью vue-cli, поэтому сегодня я планирую написать о том, как их еще улучшить и интегрировать на полку vue- cli 3.0.Фронтальная полка с базовыми функциями в основном включает в себя следующие функциональные точки:
- расширение упаковки webpack
- css: поддержка sass, normalize.css
- рем-макет
- Дизайн маршрутизации: ленивая загрузка, предварительная проверка, проверка достоверности
- API-дизайн
- Дизайн тела запроса – Защита от дубликатов отправки
- vuex управление состоянием
расширение упаковки webpack
Самая большая особенность vue-cli3 заключается в том, что零配置
, скаффолдинг скрывает конфигурацию, связанную с веб-пакетом, в @vue\preload-webpack-plugin. Конфигурация по умолчанию может соответствовать большинству сценариев приложений. Преимущество заключается в том, что мы можем сэкономить много времени на настройку. Веб-пакет по-прежнему является чем-то вроде порога для новички Да, таким образом, новички могут уделять больше внимания кодированию Vue. Недостаток тоже очевиден, будет немного хлопотнее, когда вы захотите настроить конфигурацию самостоятельно.
Просмотр подробной конфигурации текущего веб-пакета
использоватьvue inspect
Подробный список настроек можно посмотреть
Расширить конфигурацию веб-пакета
Когда мы хотим изменить или расширить элементы конфигурации веб-пакета, мы можем добавить новые в корневой каталог.vue.config.js
Файл, список простой маленький каштан, написанный мной
// webpack 扩展
module.exports = {
baseUrl: 'production' === process.env.NODE_ENV ?
'/production-sub-path/' :
'/',
chainWebpack: config => {
config.module
.rule('images')
.use('url-loader')
.tap(options => Object.assign(options, { limit: 500 }));
},
devServer: {
open: 'darwin' === process.platform,
// host: '0.0.0.0',
port: 8088,
https: false,
hotOnly: false,
// proxy: 'https://api.douban.com' // string | Object
proxy: 'http://localhost:3000' // string | Object
},
lintOnSave: false
};
Официальный сайтСтандартные инструменты для разработки Vue.jsВведение очень подробное, а также есть китайская версия, которую очень легко понять.
дерзкая поддержка
- Это написано в компоненте
<style lang="scss"></style>
может поддерживать синтаксис scss - Импортируйте другие файлы scss в компонент следующим образом.
<style lang="scss">
@import "./assets/style/app";
</style>
- Используя пользовательские функции и примеси в компонентах, я не нашел способа ссылаться на них глобально, я могу только вручную ссылаться на них в файлах компонентов, которые необходимо использовать, следующим образом
<style lang="scss">
@import "../assets/style/functions";
@import "../assets/style/mixin";
.rem {
height: px2rem(187.5px); //自定义的函数
}
.mimi {
@include clearfix(); //自定义的mixin
}
</style>
- Чтобы сгладить различия между браузерами, нам нужно ввести normalize.css
// app.scss
@import "./node_modules/normalize.css/normalize"; //引用第三方normalize
@import "custom_normalize"; // 自定义的normalize
рем-макет
Это хороший выбор для использования макета rem на мобильной стороне, поскольку мы используем в нем scss, мы можем использовать функции для упрощения нашей повторяющейся вычислительной работы. Дизайну обычно дается двукратное изображение шириной 750 пикселей, тогда мы можем установить эталон какdocument.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
Затем напишите функцию преобразования следующим образом:
// _functions.scss
@function px2rem($px) {
$rem: 75px;
@return ($px/$rem) + rem;
}
Когда мы его используем, мы можем написать
.rem {
height: px2rem(300px); // 2倍图下的宽是300px,
}
Преобразование в css
.rem {
height: 4rem;
}
дизайн маршрутизации
В основном это включает отложенную загрузку маршрутизации, предварительную проверку маршрутизации и логику проверки достоверности.Ниже приведена простая маршрутизация, которую я написал.
import Vue from 'vue';
import Router from 'vue-router';
// 路由懒加载
const getComponent = (name: string) => () => import(`./views/${name}.vue`);
Vue.use(Router);
const router = new Router({
routes: [
{
path: '/',
name: 'home',
component: getComponent('home')
},
{
path: '/about',
name: 'about',
component: getComponent('about'),
meta: {
auth: true
}
},
{
path: '*',
name: 'not_fount',
component: getComponent('notFount')
}
]
});
/**
* 路由前置检查
*/
router.beforeEach((to, from, next) => {
// 合法性校验
if (to.meta.auth) {
console.log('into auth');
next();
}
next();
});
export default router;
API-дизайн
новыйservice
Папка используется для хранения скриптов API, а файлы разделены в соответствии с бизнес-модулями, такими как файл API, связанный с пользователем, файл, связанный с покупкой,api.ts
представляет собой набор API каждого модуля, как показано ниже
// service/api.ts
export { userApi } from './user';
export { buyApi } from './buy';
// service/user.ts
export const userApi = {
/**
* 获取用户数据
*/
userInfo: '/node_api/read/userInfo'
};
// service/buy.ts
export const buyApi = {
/**
* 购买
*/
shoping: '/node_api/shop/buy'
};
Это разделение сделано для того, чтобы сделать структуру проекта и бизнес-структуру достаточно ясной и в то же время избежать проблемы слишком длинного одного файла.
Вторичная инкапсуляция HTTP-запроса
Для отправки http я использую очень популярныйaxios
, делаю на его основе простую инкапсуляцию, а потом выставляюrequest
объект для вызова. Вторичная упаковка в основном предназначена для решения следующих проблем
-
Упростите параметры, назначьте значения по умолчанию для некоторых часто используемых параметров, упростите внешнее использование и сделайте их более общими и удобными для устранения неполадок.
-
Унифицированная обработка возвращаемых сообщений, нам обычно необходимо выполнять одинаковую обработку для некоторых высокочастотных сценариев, таких как коды ошибок, отсутствие входа в систему и другие сценарии, которые могут быть обработаны единообразно в предоставленном им перехватчике возвращаемого ответа.
-
Предотвращение повторных отправок. Из-за сетевых и серверных факторов обработки иногда ответ интерфейса будет медленным, поэтому пользователь может многократно нажимать кнопку в течение очень короткого периода времени, и если первый запрос не возвращается, он инициирует новый запрос, то мы можем что-то сделать в предварительном перехватчике, предоставленном axios. Про предотвращение повторных запросов я писал в предыдущей статье,Внешний интерфейс предотвращает повторную отправку пользователями - jsЗаинтересованные друзья могут посмотреть.
Согласно вышеизложенным пунктам, ниже представлен файл запроса, который я инкапсулировал, идеи относительно просты, поэтому я не буду говорить больше.
import axios from 'axios';
import qs from 'qs';
const Axios = axios.create({
baseURL: '/',
timeout: 10000,
responseType: 'json',
withCredentials: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
}
});
const CancelToken = axios.CancelToken;
const requestMap = new Map();
// 请求前置拦截器
Axios.interceptors.request.use(
config => {
// 防重复提交
const keyString = qs.stringify(Object.assign({}, { url: config.url, method: config.method }, config.data));
if (requestMap.get(keyString)) {
// 取消当前请求
config.cancelToken = new CancelToken((cancel) => {
cancel('Please slow down a little');
});
}
requestMap.set(keyString, true);
Object.assign(config, { _keyString: keyString });
if (config.method === 'post' || config.method === 'put' || config.method === 'delete') {
// 序列化
config.data = qs.stringify(config.data);
}
return config;
},
error => {
return Promise.reject(error);
}
);
// 返回响应拦截器
Axios.interceptors.response.use(
res => {
// 重置requestMap
const config: any = res.config;
requestMap.set(config._keyString, false);
if (res.status === 200) {
return res.data;
}
// todo 弹窗提示等
console.log(`request error:${res}`);
},
error => {
return {
code: -1
};
}
);
/**
* @description
* 请求
* @param url
* @param data
* @param method
*/
const request = (url: string, data = {}, method = 'post') => {
return Axios({
method,
url,
data,
params: method.toUpperCase() === 'GET' && data
});
};
export { request };
vuex управление состоянием
Здесь я делю файловую структуру в соответствии с бизнес-модулем, как показано ниже.
Разделенный на модуль домашней страницы и пользовательский модуль, каждый модуль имеет свои собственные независимые мутации состояния и т. д.store.ts
, импортируйте файлы каждого модуля следующим образом
import Vue from 'vue';
import Vuex from 'vuex';
import index from './indexModule/index';
import user from './userModule/user';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
user,
index
}
});
Все замечают, что естьstore_types.ts
файл, этот файл в основном используется с ts, содержание файла следующее
export enum UserType {
/**
* 模块名称
*/
'MODULE_NAME' = 'user',
/**
* 增加次数
*/
'ADD_COUNT' = 'addCount',
/**
* 计算属性-获取十倍的值
*/
'GET_TEM_COUNT' = 'getTenCount'
}
Посмотрите, как используется компонент:
<script lang="ts">
import { UserType } from '@/store/store_types';
import { Component, Prop, Vue, Watch,Emit } from 'vue-property-decorator';
import {
Action,
Getter,
Mutation,
namespace,
State
} from 'vuex-class';
@Component
export default class Test extends Vue {
@State(state => state[UserType.MODULE_NAME].count) public fff!: number;
@Getter(`${UserType.MODULE_NAME}/${UserType.GET_TEM_COUNT}`) public tenCount!: number;
@Mutation(`${UserType.MODULE_NAME}/${UserType.ADD_COUNT}`) public addCount!: any;
}
</script>
Хотя писать так немного запутанно, есть преимущество, заключающееся в том, что мы можем четко знать описание методов и свойств с помощью аннотаций.
резюме
Вышеприведенное разработано в соответствии с общими сценами в моей работе. Я надеюсь, что это может быть полезно для моих друзей. Если дизайн не подходит, я приглашаю своих друзей обсудить вместе в области сообщений ~