Кратко опишите инкапсуляцию базовой конфигурации и совместное использование разработки моей команды проекта Vue.

Vue.js
Кратко опишите инкапсуляцию базовой конфигурации и совместное использование разработки моей команды проекта Vue.

Эта статья разрешает эксклюзивное использование общедоступной учетной записи сообщества разработчиков Nuggets, включая, помимо прочего, редактирование, пометку оригинальности и другие права.

Введение

Эта статья в основном приноситvue 基础架构, мы все знаем,Vue3.0 назадVue2.0Будет финальная версия, а значитVueМы открыли новую эру, но не все проекты могут двигаться к новой эре кораблей вместе. Эта статья в основном является продолжением предыдущей статьи о методах оптимизации. Это продолжение в основном касается вещей, связанных с командной разработкой. Соответствующие плагины и библиотеки были представлены лишь немного. Если эта статья может продвинуть вашу производственную линию, пожалуйста, нажмите "Нравится" Это.

Если вы настроите связанные классы, вы можете выполнить поиск соответствующих сообщений о совместном использовании или прочитать мои предыдущие статьи.Содержание этой статьи больше подходит для командной разработки, и большинство статей о совместном использовании, не связанных с инструментальной цепочкой, могут привести к некоторому техническому мышлению.

предисловие

Во многих случаях дляvueЧто касается проектов, многие друзья, которые только начали или скомпрометированы бизнесом, в основном из Baidu.CVНабор полок, которые можно увидеть, например, обычныеD2Admin,vue-element-admin, провести вторую итеративную разработку, сам проект очень качественный, и в своемtemplateВнесение изменений в середине может дать проекту хорошее базовое окружение в начале, но если вы не потратите время на то, чтобы разобраться в деталях. Что касается последующего разминирования, то это, несомненно, очень сложно, поэтому большинство передовых групп реконструируют свой собственный набор базовых комплектов строительных лесов.webpackобработаны, а также основаны наVueCliТо, что создано, в конечном итоге является собственностью его собственной команды.От обмена технологиями до разделенной практики это может принести более или менее удобство разработки небольшим партнерам команды. Изменения в последующих членах команды также могут быть быстро запущены в производство.

Что вы наделали?

  • Базовая инкапсуляция HTTP-запроса
  • Обычное управление HTTP-запросами
  • Управление данными Mmixin
  • документация проекта jsdoc
  • обработка исключений журнала
  • Управление компонентами и страницами
  • Общие команды
  • Sass или SCSS?
  • @mixin и %placeholder
  • eslint

Что делает базовый HTTP-запрос?

обработка ошибок

Вот тот, который сейчас более совместимaxios, можно сказать, что это лучшая библиотека запросов по сравнению сfetch, у обоих есть свои преимущества (я начал использоватьfetch).这一部分其实无非就是封装一些公共调用时需要处理的行为,如:token,请求拦截,响应拦截,错误码约定,异常上报,中间件и ряд основных моделей поведения.

В следующем примере, когдаHTTPКогда в запросе есть ошибка, первый проходgetEnvПолучите текущую среду разработки, если даdev(开发环境下)просто сделай простоconsole.log, в среде, не предназначенной для разработки, сообщается об аномальном мониторинге, который относится как к переднему, так и к внутреннему интерфейсу.

/**
 * 异常错误处理
 * @example
 * handleError ('我发生了错误', '后端约定message')
 * @param { string } error console错误信息
 * @param { string } msg 后端message捕获
 */
function handleError (/* @type { string } */ error, /* @type { string } */msg) {
  if (getEnv() === 'dev') {
    tools.log.danger('>>>>>> HTTP Error >>>>>>')
    console.log(error, msg)
  } else {
    Store.dispatch('logs/push', {
      message: msg,
      type: 'danger'
    })
  }
}

RESTFul

По сравнению с некоторыми перехватчиками они очень просты.Все, на что нужно обратить внимание, это сформулировать некоторые правила в соответствии с некоторыми спецификациями команды, такими как общиеcodeкод и другие методы, в большинстве случаев, если не случайно, 99% интерфейсов успешно запрашиваются, но из-за специфики будет внутреннийcodeСтатус для определения вперед назад. Аналогично, в работе интерфейса некоторый статус также синхронизируется с запрашивающим методом и интерфейсом, и ссылка выглядит следующим образом:

  • GET: 200 OK
  • POST: 201 Created
  • PUT: 200 OK
  • DELETE: 204 No Content

Сегодня используется большинство интерфейсов.RESTful, если вы не знаетеRESTfulЧто это, вы можете видеть@阮一峰статья для предварительного понимания.RESTful API Best Practices @ веб-журнал Ruan Yifeng

Механизм кода состояния

такой жеcodeМы также настраиваем ежедневную разработку некоторого кода состояния, когда нам нужно использовать第三方APIКогда внешнему и внутреннему компонентам необходимо быстро определить, связана ли проблема с их собственной службой или другими службами (например, мидл-офисом), мы настроили некоторые из стыковочных служб.codeдля описания обработки этого типа ошибки. Вы можете обратиться к следующему, что фактически создано в объекте:image.pngпользовательский код

code условие описывать
30000 invalid credential недействительные учетные данные
30001 invalid connect_type неверный тип соединения
30001 invalid group_conf_id недействительный group_conf_id
...... ...... ......

Когда мы уточняем некоторые аномалии, в настоящее время они могут быть очень подробными. Вот несколько ссылок для WeChat:

40039 invalid url size неверная длина URL
40048 invalid url domain неверный URL-адрес доменного имени
40054 invalid sub button url domain Неверный адрес домена кнопки подменю
40055 invalid button url domain Недопустимое доменное имя URL кнопки меню
40066 invalid url неправильный адрес
41001 access_token missing Отсутствует параметр access_token
41002 appid missing отсутствует параметр appid
41003 refresh_token missing Отсутствует параметр refresh_token
41004 appsecret missing отсутствует секретный параметр
41005 media data missing Отсутствуют двоичные медиафайлы
41006 media_id missing отсутствует параметр media_id
41007 sub_menu data missing Отсутствующие данные в подменю
41008 missing code Отсутствие параметров CODE
41009 missing openid отсутствует параметр openid
41010 missing url отсутствует параметр URL
42001 access_token expired тайм-аут access_token
42002 refresh_token expired время ожидания refresh_token
/**
 * HTTP请求处理
 * @param { object } settings 请求设置
 * @param { string } [settings.withCredentials] 安全策略
 * @param { number } [settings.timeout] 超时时间
 * @param { string } [settings.baseURL] 接口地址
 * @return { Promise } HTTP请求方法
 */
function createHttpService (/* @type { object } */settings) {
  const service = Axios.create(settings)
  service.interceptors.request.use(
    config => {
      // TODO: 添加token
      const token = localStorage.getItem('access_token')
      config.headers.token = token
      return config
    },
    error => {
      return Promise.reject(error)
    }
  )
  // 响应拦截
  service.interceptors.response.use(
    response => {
      console.log(response)
      const { code, message, data } = response.data
      // 自定义提示
      if (code >= 30000) {
        console.log('>>> 自定义错误信息,全局提示处理', message)
        return data
      }
      // 正常的code
      if (code >= 200 && code < 300) {
        return data
      }

      // 错误的code, 自己处理
      if (code >= 300 && code < 600) {
        return Promise.reject(response.data)
      }
    },
    error => {
      const { status = 404 } = error?.response
      if (Object.prototype.hasOwnProperty.call(codeMessage, status)) {
        handleError(error, codeMessage[status])
      }
      throw error
    }
  )
  return service
}

const http = createHttpService({
  withCredentials,
  timeout,
  baseURL
})

Обычный http-запрос

Я прочитал несколько статей на статье, мы, как правило, ясны, согласованные запросы могут быть очень хорошими, чтобы упростить сложность пакета запроса, то же самое, когда есть белый или ваша компания, то стажер для распаковки запроса не учитывается, когда вы Доставьте миссию, чтобы завершить не равную более хорошую завершенную.

В дополнение к уменьшению фактора нестабильности кода начинающих разработчиков в команде, условный тип также сокращает написание одного кода за другим во время разработки.AxiosPromiseДублированное поведение функции. Ниже приведено основное соглашение об интерфейсе, вlogin-api.jsФайлы, написанные ниже, будут сопоставлены с请求函数 

// login-api.js
export default {
  getPerson: 'GET /person',
  setPerson: 'POST /person',
  updatePerson: 'PUT /person/:id',
  deletePerson: 'DELETE /person/:id'
}

Такие какlog.jsДля вывода результата разработчикам команды не нужно обращать внимание на саму функцию, а только на вызов. в то же время,开发环境下Вся информация об интерфейсе будет проходить черезconsole.tableВывод в консоль, при отсутствии хорошего вывода типа можно еще быстро вызвать соответствующий интерфейс для получения внутренних данных.image.png

Разделение самой функции API на самом деле является повторяющейся задачей, которая не имеет смысла для разработки разработчиков.

разные способы вызова

Для унифицированного вызова целесообразно указать два метода использования, которые являются общими в большинстве сценариев. Первый метод более консервативен и фактически передается членам для выполнения задач. Примеры:

<script>
 // 引入useServices
import { useServices } from 'framework'

// 解构接口函数
const { getPerson } = useServices()
/**
 * @module 测试页面1
 * @page
 */
export default {
  name: 'home',
  created () {
    // 请求后处理
    getPerson().then(res => {
      console.log(res)
      alert('接口请求成功')
    }, err => {
      console.log(err)
      alert('接口请求失败')
    })
  }
}
</script>

Приведенный выше пример очень прост.Я думаю, что студенты с небольшими базовыми знаниями могут видеть, что первый способ очень распространен и подходит для большинства людей, но недостатки также очевидны.Если каждый интерфейс нужно сделать один разthen & catch & finallyСлова, несомненно, являются катастрофой, поэтому родился второй метод, который более удобен для новичков. Следующий пример:

<script>
 // 引入useServices
import { useServices } from 'framework'
/**
 * @module 测试页面2
 * @page
 */
const Admin = {
  created () {
    this.getPersonData()
  },
  methods: {
    // 获取数据
    async getPersonData () {
      const [, err] = await useServices('getPerson')
      if (err) {
        alert('接口请求失败')
      } else {
        alert('接口请求成功')
      }
    }
  }
}
export default Admin
</script>

На основе оригинального API,useServices дляPromiseПоведение обертывания слоя промежуточного ПО, когда вы решите использовать запросы без состояния, этоpromise中间件Действия запускаются. и воляPromiseПосле того, как результирующая форма абстрагируется и возвращается в виде массива, в логическом блоке нам достаточно просто передатьasync & awaitОбрабатывайте данные в результатах, не сосредотачиваясь на бессмысленныхtry catch а такжеthen catch.

Причина совместимости двух методов заключается в том, что разные разработчики имеют разные привычки.Иногда разработчики думают, что обработка ошибок должна быть разрешена обработчиком, чтобы достичь цели устранения ошибок.

Управление данными Mixin (модель)

При согласованном запросе проблема нашего запроса решается единым образом, но вытекает проблема асинхронного управления данными.Вью-разработчики уже давно привычно ставят интерфейсные запросы и логику обработки данных.В вью-файлах такие как наиболее распространенный分页表格数据,基础表单显示, каждая страница объявляет многоtotal,pageSize,currentPage,tableDataВ ожидании полей и бесконечном повторении резюме после насыщенного дня я чувствую, что за сегодня проделал более 10 страниц. На самом деле, внимательные одноклассники также обнаружили, что сколько бы раз вы ни кодировали CV, есть предел совершенствованию себя, это не что иное, как совершенство, а скорость копирования и вставки быстрее, как если бы вы написали 4000 раз.helloЭто не значит, что у вас вообще 4000 слов.

Таким образом, создается компонент формы, который инкапсулирует свой собственный, и необходимо передать лишь небольшое количество параметров (например, метод HTTP-запроса) для реализации рендеринга формы. Точно так же есть и мелкие партнеры, которые упаковываютGlobal Mixinрешить эту часть задачи. Точно так же, чтобы хорошо управлять уровнем данных, я также пробую другое управление данными.По мере увеличения бизнес-логики асинхронными данными большинства страниц трудно управлять, и они будут более или менее перепутаны с логическими данными стр. Через некоторое время необходимо$dataТолько путем деконструкции и реорганизации данных в , можно понять логику.

Итак, попробовав разные решения,mixinстало первым решением, оно не похожеvuexКак правило, это будет действовать глобально, но только для смешанной страницы, поэтому после простой попытки миксин будет упакован, а абстракция станетmodelслой, этоmodelРоль уровня в основном заключается в обработке потока асинхронных данных страницы уровня меню.Данные страницы просмотра находятся в.vueв заявлении,后端数据 существуетmodel.js середина.

Базовая модель.js выглядит так

export default {
  namespace: 'Home',
  state: {
    move: {},
    a: 1,
    b: 2
  },
  actions: {
    /**
     *
     * @param { Object } state
     * @param { Object } payload
     * @param { function } set
     */
    async setUser (state, { payload, set }) {
      const data = await test()
      await set(state, 'move', data)
      return state.move
    }
  }
}

const test = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({
        user: 'wangly',
        age: 21
      })
    }, 2000)
  })
}

Затем на странице объявленные компоненты будут переданы вuseModelsСмешивание, после смешиванияMixinФормат именования уже более сложный, а текущий в настоящее время не используется.this.xxx, но единая реализацияthis.useDispatchОбрабатывается без прямого запускаmodel methodsОдинаково для всехmodelСостояние меняется, и внутри будут разные нагрузки внутри.

простой пример

Моделируйте загрузку данных на стороне сервера через простой экземпляр, процесс с нуля, чистыйmodel.jsКонтрольные данные и состояние Смоделируйте интерфейс данных с помощью следующего теста, вgetDessertsЧтобы получить, чтобы обеспечить качество чтения, смоделированные данные усекаются, вы можете обратиться кvuetifyUI Table Demoданные.

export default {
  namespace: 'Admin',
  state: {
    mockTabData: [],
    headers: [
      { text: 'Dessert (100g serving)', value: 'name' },
      { text: 'Calories', value: 'calories' },
      { text: 'Fat (g)', value: 'fat' },
      { text: 'Carbs (g)', value: 'carbs' },
      { text: 'Protein (g)', value: 'protein' },
      { text: 'Iron (%)', value: 'iron' }
    ]
  },
  actions: {
    /**
     *
     * @param { Object } state
     * @param { Object } payload
     * @param { function } set
     */
    async getDesserts (state, { payload, set }) {
      const data = await test()
      console.log(data)
      if (data) {
        state.mockTabData = data
      }
    }
  }
}

const test = () => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve([
        {
          name: 'Frozen Yogurt',
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0,
          iron: '1%'
        },
        // ... 省略数据
      ])
    }, 2000)
  })
}

на странице, вcreatedВ крючок, позвонивthis.useDispatch('Admin/getDesserts')для сбора данных, а затемAdmin.headers,Admin.mockTabDataНазначьте его соответствующему параметру компонента и передайте当前modelПобочные эффекты метода используются для управления скелетным экраном.

всеmodelметод будетdataСоздайте состояние побочного эффекта в , чтобы избежать конфликтов, избегайте определений в данныхmodel, чтобы не бытьmodel.jsпокрытие.

<template>
  <div>
    <v-data-table
      v-if="!model['Admin/getDesserts']"
      :headers="Admin.headers"
      :items="Admin.mockTabData"
    ></v-data-table>
    <v-sheet v-else>
      <v-skeleton-loader :boilerplate="false" type="table"></v-skeleton-loader>
    </v-sheet>
  </div>
</template>

<script>
import { useModels } from 'framework'
/**
 * @module 测试页面2
 * @page
 */
const Admin = {
  created () {
    this.useDispatch('Admin/getDesserts')
  }
}
export default useModels(Admin, ['Admin'])
</script>

Взгляните на эффект, очень простые изменения отклика управляющих данных:

demo.gif

В этом функциональном эксперименте это только для справки. Стресс-тест производительности все еще продолжается QAQ.

Документация проекта JSDOC

Документация проекта - это очень важная вещь, не переверните свой собственный код, если бизнес большой, около трех месяцев, вы обрабатывались, проект может потерять какую-то визуальную память, на этот раз, на этот раз вы продолжаете поддерживать или новую продолжать поддерживать Трудная вещь, в то же время необходимо рассмотреть, когда проект в Генерал, а затем время новых участников, огромныхcomponents,utils,apiЭто заставит новичков чувствовать себя не в состоянии начать, поэтому документ особенно ценен. Потом некоторые одноклассники спрашивали, я слишком занят делами, и мне приходится тратить время на сортировку документов, какое мне дело до чужих дел?

Хороший проект должен иметь хороший документ.Исходя из такого рода проблем, был введен инструмент для создания документа.В этот период документ также был улучшен, чтобы стать более подходящим.vueсебя, прежде всего,@moduleбыл реконструирован, проходя@pageЧтобы объявить страницу, перейдите@componentОбъявите общедоступный компонент, как в следующем примере:

<template>
  <div>2222</div>
</template>

<script>
import { useModels, useServices } from 'framework'
/**
 * @module 测试页面2
 * @page
 */
const Admin = {
  created () {
    this.getPersonData()
  },
  data: () => ({
    /** @type { boolean } 当前是否折扣  */
    discount: false,
    /** @type { number } 当前tab页面 */
    currentTab: 1
  }),
  methods: {
    /**
     * 获取用户数据
     * @method getPersonData
     * @returns { void } - 无返回结果
     */
    async getPersonData () {
      const [, err] = await useServices('getPerson')
      if (err) {
        alert('接口请求失败')
      } else {
        alert('接口请求成功')
      }
    }
  }
}
export default useModels(Admin, ['Admin'])
</script>

затем, наконец, пройтиyarn docкоманда для создания документации:

yarn doc

Эффект выглядит такimage.pngВидно, что некоторые аннотации сейчас очень стандартизированы, но они все еще не совершенны.Главным фактором является то, чтоjsdocЕсли команде необходимо провести рефакторинг темы документа, он может провести рефакторинг самостоятельно, что относительно просто.

Примеры в тексте приведены только для справки, перейдите к аннотированному документу:jsdoc

собственный журнал разработки

дляconsoleИспользование , смотрел наD2AdminКогда мы клонировали его копию для журнала ошибок, нам не нужно копировать некоторые из наших собственныхconsleтоже собирает, ноconsoleЕсть также промежуточные оценки, если они сданыconsole.errorЕсли он в процессе, он может быть перехвачен и передан в фон, поэтому log.js переписывается для отладки разрабатываемой и бета-версий.

const log = {}

/**
 * @description 返回这个样式的颜色值
 * @param {String} type 样式名称 [ primary | success | warning | danger | text ]
 */
function typeColor (type = 'default') {
  let color = ''
  switch (type) {
    case 'default':
      color = '#303133'
      break
    case 'primary':
      color = '#409EFF'
      break
    case 'success':
      color = '#67C23A'
      break
    case 'warning':
      color = '#E6A23C'
      break
    case 'danger':
      color = '#F56C6C'
      break
    default:
      break
  }
  return color
}

/**
 * @description 打印一个 [ title | text ] 样式的信息
 * @param {String} title title text
 * @param {String} info info text
 * @param {String} type style
 */
log.capsule = function (title, info, type = 'primary') {
  console.log(
    `%c ${title} %c ${info} %c`,
    'background:#35495E; padding: 1px; border-radius: 3px 0 0 3px; color: #fff;',
    `background:${typeColor(
      type
    )}; padding: 1px; border-radius: 0 3px 3px 0;  color: #fff;`,
    'background:transparent'
  )
}

/**
 * @description 打印彩色文字
 */
log.colorful = function (textArr) {
  console.log(
    `%c${textArr.map(t => t.text || '').join('%c')}`,
    ...textArr.map(t => `color: ${typeColor(t.type)};`)
  )
}

log.default = function (text) {
  log.colorful([{ text }])
}

log.primary = function (text) {
  log.colorful([{ text, type: 'primary' }])
}

log.success = function (text) {
  log.colorful([{ text, type: 'success' }])
}

log.warning = function (text) {
  log.colorful([{ text, type: 'warning' }])
}

log.danger = function (text) {
  log.colorful([{ text, type: 'danger' }])
}

export default log

Эффект, как показано ниже:

log.default('>>> 我是一些默认提示')
log.primary('>>> 我是一些标记提示')
log.success('>>> 我是一些成功提示')
log.warning('>>> 我是一些警告提示')
log.danger('>>> 我是一些错误提示')

image.png

Управление компонентами и страницами

В процессе разработки также будет очень полезно выработать несколько хороших привычек для опыта работы над проектом.Написание кода похоже на рукоделие.Будьте внимательны и логичны, чтобы узнать больше и сократитьP0 BUGЕсли вы не догоняете проект, а та же проблема сохраняется, то органы чувств очень плохи. Итак, запомните следующие советы, надеюсь, они вам помогут

Файл подкачки

Здесь рекомендуется, чтобы все уровни страницы размещаются под деревом, меню каталогов использует папки и вид по умолчаниюindex.vue, все имена должны быть написаны в нижнем регистре camelCase, желательно строчными буквами, например:home,user. Подождите, компоненты равномерно размещены на стартовой страницеcomponents, а имя — это большой верблюжий регистр с именем модуля, напримерAdminвнизHeaderкомпонентAdminHeader.vue, при использовании:<admin-header/>, при введении используйте единообразно@/views/admin/components/xxxимпорт. Все меню находятся в меню первого уровня в глубине, а имя страницы предназначено для лучшего различения и предотвращения путаницы компонентов.image.png

экспорт метода

Много раз разные члены команды пишутutilsКогда , используйте функцию стрелки, также используйтеfunctionПоэтому для объявления рекомендуется использовать здесь единообразноexport functionв видеjsДекларация следующего содержания:

import asyncAxiosInstance from '@/plugin/createService'
import currentModels from '@/plugin/createModel'
/**
 * 获取当前开发环境状态
 * @example
 * getEnv()
 * @export { Function } getEnv 当前环境方法【开发环境】【测试环境】【生产环境】
 * @return {String} 当前环境【dev】【test】【pro】
 */
export function getEnv () {
  return process.env.VUE_APP_MODE || 'dev'
}

/**
 * 允许当前组件使用model数据依赖
 * @param { object } component 当前的Vue组件
 * @param { Array<string> } models 需要注入的模块
 * @param { boolean } isDispatch 是否开启dispatch
 * @returns { object }
 */
export function useModels (component, models, isDispatch = true) {
  const current = []
  currentModels.forEach(item => {
    if (models.includes(item.name)) {
      current.push(item.mixin)
    }
  })
  if (isDispatch && current.length > 0) {
    current.push(currentModels[0].mixin)
  }
  console.log(current)
  if (component?.mixins) {
    const preMixin = component.mixins
    component.mixins = current.concat(preMixin)
    return component
  }
  component.mixins = [...current]
  console.log(component)
  return component
}

Общие команды

В ежедневной разработке некоторые инструкции могут добиться вдвое большего результата с половиной усилий, но инструкции нужно выполнять в соответствии с делом.В то же время дизайнеру также необходимо пометить документ при оформлении, чтобы он был удобный для просмотра членами команды. Для регистрации рекомендуются следующие команды:

  • Инструкция внешнего щелчка v-click-outside: при нажатии на несвязанный элемент элемент будет скрыт
  • Монитор элементов v-intersect: определяет, виден ли элемент в пользовательском представлении.
  • Слушатель v-resize zoom: команда прослушивания при увеличении окна
  • Монитор прокрутки v-scroll: вы можете гибко наблюдать за изменениями прокрутки связанных элементов.
  • сенсорный монитор v-touch: может гибко отслеживать сенсорное поведение в мобильном терминале и генерировать обратные вызовы
  • Монитор разрешений v-auth: переписать изv-permissionВ основном выполняйте проверку разрешений на уровне кнопок и проверку разрешений на странице.

Инструкционный ресурс

Использовать SASS или SCSS?

Лучшее на данный моментCSS扩展语言ещеSASS а такжеLESSОба большие плохие неплохие, возможно нужно заменить по команде, какая разница их не использовать. В девелоперских проектах дляSASSЯ рекомендую сначала (не SCSS), если вы не знакомы с использованиемSASSМои одноклассники будут чувствовать себя очень античеловечно, но если ваши нормы хороши, я думаю, вы можете прочитать следующий абзац.SASSКод:

@mixin flex ($mod: flex, $justifyContent: center, $alignItems: center, $direction: initial)
  display: $mod
  justify-content: $justifyContent
  align-items: $alignItems
  flex-direction: $direction
// end flex mixin ...

При написании CSS рекомендуется добавлять абзац в концеendКомментарии используются как завершение логических символов, чтобы различать код блоков стилей и предотвращать логическую путаницу.Когда большое количество стилей плохо поддерживается, я думаюSCSSЧувство безопасности относительно высокое. Точно так же, когда обслуживание хорошее,SASSНесомненно лаконичнее. Конечно, это также подвержено ошибкам.

У них одна и та же цель, и их можно выбирать в соответствии с привычками членов команды.

@mixin и %placeholder

первый,@mixinПодходит для написания логическихcss, как самое основноеflex, через который можно пройтиparamsРазличные настройки, это%placeholderотсутствует, но%placeholderПри наследовании статических стилей повторение может быть уменьшеноcss, чтобы уменьшить повторяющийся код, большинство используемых сценариев:基本卡片样式,统一的组件样式Используйте его, когда нет отклонений в дизайн-проекте, поэтому бездумное использование не требуется.@mixin,иногда%placeholderболее ароматный.

Например, используя соотношение:

%demo
  color: red
  font-size: 20px
  border: 1px solid red
 // end ...

.test1
  @extend %demo
// end ...

.test2
  @extend %demo
// end ...

.test3
  @extend %demo

Как и в приведенном выше коде, используйте%placeholderРезультирующий стиль будет выглядеть так:

.test1, .test2, .test3 {
  color: red
  font-size: 20px
  border: 1px solid red
}

а если заменить на@mixin, их результат таков:

@mixin demo()
  color: red
  font-size: 20px
  border: 1px solid red
// end ...

.test1
  @include demo()
// end ...

.test2
  @@include demo()
// end ...

.test3
  @@include demo()
// end ...

После компиляции:

.test1 {
  color: red
  font-size: 20px
  border: 1px solid red
}
.test2 {
  color: red
  font-size: 20px
  border: 1px solid red
}
.test3 {
  color: red
  font-size: 20px
  border: 1px solid red
}

Излишне говорить, что вы должны знать, как его использовать.

ESLint

В идеале большинство фронтенд-команд должны иметьEslint, как стандарт качества кода, а только стандарт, сGit CommitПредварительное действие может проверить, квалифицирован ли код, чтобы предотвратить отправку нестандартного кода в репозиторий.Это действие требует, чтобы разработчики выработали хорошие привычки кодирования и осведомленность о качестве кода.

При использованииVS CODEЗатем вам нужно настроить компилятор для включения проверки правил.При нарушении синтаксического предупреждения будет выведено следующее предупреждение:image.png

Не рекомендуется компилировать код напрямую при непосредственном коммите, Eslint помогает разработчикам развивать свой код, а не является поверхностным инструментом.

Исходный код и ресурсы

Суммировать

Неосознанно я два месяца не писал статьи.Помимо занятости после смены работы, провожу время с одним человеком и чтением литературы.Очень приятно удивлен, увидев, что многие друзья перепечатывают мои статьи.Требования к качеству статья выше.По мере накопления опыта работы и технического обучения, я надеюсь, что содержание статьи будет технически улучшено для вас.

Эта статья должна стать преемницей предыдущей.Vue开发中的一些常见套路和技巧(上)Второй том, по сравнению с предыдущим, в этой статье больше вещей и она более практичная.Помимо продвижения отдельных разработчиков, она больше о командной разработке. Фронтенд-инжиниринг постепенно дошел до совершенства, а формирование команды стало решающим.Несколько лет назад не было фронтенд-архитектуры, а теперь фронтенд-архитектура стала критически важной в разработке. Это все приливы времени, только благодаря постоянному обучению и размышлению может быть небольшой спорадический всплеск на вздымающихся волнах.

Написание поздно ночью в виде статьи Vue, которой поделится небольшой интерфейс Vue + React, если это полезно для вас или вашей команды, поставьте лайк автору, чтобы переодеться на зиму. Зимой в Ханчжоу очень холодно.