«Построение веб-проекта, разделенного спереди и сзади с нуля» на практике

Архитектура внешний интерфейс Vue.js axios
«Построение веб-проекта, разделенного спереди и сзади с нуля» на практике

Если вы хотите делать хорошие вещи, вы должны сначала оттачивать свои инструменты — продолжать полировать интерфейсную архитектуру.

Извините за задержку, счастливый 1024

Эта статья постоянно обновляет адрес

заполнить яму

В прошлый раз одноклассник действительно упомянул эту проблему, спасибо за внимание. @_новичек

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

Чтобы позаботиться о студентах, которые не подписались на меня в режиме реального времени, код каждой главы публикуется отдельно в моемGithubБлог, никаких обновлений покрытия [если только код не изменен для устранения ошибок], что позволяет избежать2019Нянь Сяомин просмотрел первые две главы иGithubОкончательный код версии находится в оцепенении (releaseНе особо дружелюбный)

Мы изменили указанный выше renderer/src на более простой для понимания src/renderer , что на самом деле является вопросом привычки программирования.

Проблема с renderer/src выше

eslint-config-alloy: Если вы хотите написать более стандартизированный код, вы можете обратиться к этому правилу.

Перейдем к теме этой главы


axios

Если вы используете vue, вы обнаружите, что Vue не может отправлять запросы, поэтому вы гуглите и обнаруживаете, что можете использовать Vue-Resource. Вы спрашиваете других, как обстоят дела с Vue-Resource, и он говорит: не используйте Vue-Resource, потому что Vue-Resource официально прекратил поддержку, вам следует использовать Axios или fetch. Но мы хотим использовать ES6 и исключить выборку ES5 (и, конечно, выборку ES6), здесь мы используем Axios!

Tips

Вот еще научно-популярное: когда зависимости нужно ставить в зависимости и когда зависимости нужно ставить в devDependencies:

devDependencies: как следует из названия, только в режиме разработки (dev), таком как: webpack.,Сюда помещаются .loader, eslint, babel, те, которые вообще не используются при упаковке и развертывании, а нуждаются только в компиляции, обнаружении и конвертации в разработке. зависимости: например: axios, chart, js-cookie, less, lodash, underscore и другие библиотеки времени выполнения или классы инструментов и другие связанные зависимости, которые нам нужно разместить здесь

Но в принципе не волнуйтесь, на официальном сайте есть инструкция по запуску, но нужно понимать смысл, не копируйте механически.

Представляем Аксиос

  • Воспроизвести последнюю

2018-09-28скриншот npmjs.com

  • добавить зависимости
"dependencies": {    
    "axios": "^0.18.0"
 }

Основываясь на содержании предыдущей главы, не забудьте снова загрузить npm i.

Помните наш автоматически сгенерированный скрипт главной страницы vue main.js?

пакетные аксиомы

мы вsrc/renderer/utilsСоздатьrequest.jsВ этом скрипте запроса выполните некоторую необходимую инкапсуляцию для AXIOS, вероятно, содержимое является использование Axios axios.interceptors для перехвата запросов и ответов, определить префикс API и обрабатывать некоторые общие коды состояния HTTP.

  • Документация перехватчиков

Я написал как можно больше подробных заметок для всех.

// src/renderer/utils/request.js
import axios from 'axios'

//这里一般指后端项目API的前缀,例如 /baidu/*/*/1.api  /mi/*/*/2.api
const BASE_API = ""

export function axiosIntercept(Vue, router) {
    const axiosIntercept = axios.create({
        baseURL: BASE_API
    })

    //http request 拦截器 一般用来在请求前塞一些全局的配置、或开启一些 css 加载动画
    axiosIntercept.interceptors.request.use(
        (config) => {
            // 判断是否存在token,如果存在的话,则每个http header都加上token
            // if (store.getters.accessToken) {
            //     console.log(store.getters.accessToken)
            //     config.headers.Authorization = `token ${store.getters.accessToken}`;
            // }

            //todo:加载动画

            //若有需求可以处理一下 post 亦或改变post传输格式
            if (config.method === 'post') {

            };

            return config;
        }, function (err) {
            return Promise.reject(err);
        });


    //http response 拦截器 一般用来根据一些后端协议特殊返回值做一些处理,例如:权限方面、404... 或关闭一些 css 加载动画
    axiosIntercept.interceptors.response.use(function (response) {
        // todo: 暂停加载动画
        return response;
    }, function (err) {
        //捕获异常
        if (err.response) {
            switch (err.response.status) {
                case 401:
                    // do something 这里我们写完后端做好约束再完善
            }
        }
        return Promise.reject(err);
    });
    return axiosIntercept;
}


Вы все еще помните скрипт главной страницы vue main.js, сгенерированный vue-cli, здесь нам нужно сделать связь между Axios и Vue.

// src/renderer/main.js
import axios from 'axios'
import { axiosIntercept } from './utils/request'

// 将Axios扩展到Vue原型链中
Vue.prototype.$http = axiosIntercept(Vue)

Таким образом, мы пишем бизнес-логику и используем this.$http непосредственно в контексте Vue для отправки запросов. Он реализует как перехват, так и совместное использование состояния.

знай это, знай это

  • Какой смысл это делать?

Сохраняйте код и делайте код более удобным для чтения

  • Почему?

Расширьте цепочку прототипов, заставьте среду выполнения Axios совместно использовать содержимое цепочки прототипов Vue и уменьшите количество временных переменных, которые ссылаются на Vue.

  • взять каштан

традиционная ситуация

import axios from 'axios'


new Vue({
  data: {
    user: ""
  },
  created: function () {
    //此时作用域在 Vue 上,缓存起来,要依赖此变量
    let _this = this;
    axios.get("/user/getUserInfo/" + userName).then(res => {
            if (res.data.code === 200) {
                //此时作用域在axios上,拿不到vue绑定的值,只能借助刚才缓存的_this上下文
                _this.data.user = res.data.user
            }
        });
    }
})

после прокси

 


new Vue({
  data: {
    user: ""
  },
  created: function () {
    // axios 成为了 vue 的原型链一部分,共享vue状态。
    
    this.$http.get("/user/getUserInfo/" + userName).then(res => {
            if (res.data.code === 200) {
                //注意,axios回调,应该尽量使用箭头函数,可以继承父类上下文,否则类似闭包,还是无法共享变量、
                // 更优雅了一些
                this.data.user = res.data.user
            }
        });
    }
})

Если вы не понимаете прототип, вы можете просмотреть статьи, которые я написал ранее

proxy

Сначала сделайте это кратко, сделайте небольшое покрытие для разделения спереди и сзади.

webPack

  • Псевдонимы для webPack
resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': resolve('src/renderer'),
    }
  },

Для более элегантного использования псевдонимы могут быть созданы для каждого часто используемого каталога.

resolve: {
   extensions: ['.js', '.vue', '.json'],
   alias: {
     'vue$': 'vue/dist/vue.esm.js',
     '@': resolve('src/renderer'),
     'assets': resolve('src/renderer/assets'),
     'components': resolve('src/renderer/components'),
     'container': resolve('src/renderer/container'),
     'utils': resolve('src/renderer/utils')
   }
 },

Междоменные проблемы для производства и разработки

dev — команда, запущенная во время разработки build — это директива, которая будет упакована webPack во время предварительного выпуска.

Предполагая, что автор является только фронтендом, обычно в процессе разработки и отладки неизбежна необходимость стыковки API со студентами в бэкенде, и неизбежно возникнут междоменные проблемы. Конечно, традиционный javaWeb не требует междоменного доступа (любая разница между IP-портами домена является междоменной). При отладке в режиме DEV мы пытаемся выбрать интерфейсную среду, чтобы избежать междоменных проблем, и не будем собирать или изменить внутренний код. .

Кросс-происхождение предназначено только для JavaScript, потому что разработчик считает скрипты в браузере небезопасными.

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

пример API сообщества cnode nuggets

cnodejs.org/apiAPI вышеприведенного cnode можно вызывать по желанию, потому что бэкэнд выполняет обработку.

Проверьте Наггетс:Небольшая тестовая временная шкала API-немедленно.Nuggets.IM/V1/get list B…Сделайте запрос, не случайно, браузер сделал междоменную тревогу.

О, давайте адаптируем агент узла

Официальный пример здесь:v UE JS-templates.GitHub.IO/Web pack/pro…

Расширить прокси-таблицу:


proxyTable: [{
      //拦截所有v1开头的xhr请求
      context: ['/v1'], 
      target: "https://xiaoce-timeline-api-ms.juejin.im",
      cookieDomainRewrite: {
        // 不用cookie
      },
      changeOrigin: true,//重点,此处本地就会虚拟一个服务替我们接受或转发请求
      secure: false
    }],

Отправьте запрос еще раз.

  • Рад получить данные

Таким образом, проекты, которые отделены от передней и задней части, могут использовать swagger для тестирования интерфейса, никого не беспокоя. Реализуйте свою собственную бизнес-логику и реализуйте ее просто.

Код:

// blog/index.vue
<template>
  <div class="Blog">
    <h1>{{ msg }}</h1>
     
  <div v-for="(blog,index) in blogList" v-bind:key="index">
    <h3 >
      <a :href="`https://juejin.cn/book/`+blog.id" >
        <span>{{blog.title}}</span>
      </a>
      
      </h3>
  </div>
     
  </div>
</template>

<script>
export default {
  name: "Blog",
  data() {
    return {
      msg: "掘金小册一览",
      blogList: []
    };
  },
  created() {
    this.getBlog();
  },
  methods: {
    getBlog() {
      this.$http.get("/v1/getListByLastTime?src=web&pageNum=1").then(res => {
        this.blogList = res.data.d;
      });
    }
  }
};
</script>

выпускать

  • Грамотность

После написания кода и его развертывания в сети, после клонирования кода в сети Npm не запустит dev 😆, будет слишком много мусорных зависимостей, которые принесут пользователям катастрофические сетевые запросы, обычно после упаковки с помощью webPack Publish to web service of сервер.

бегать

 npm run build

Каталог упаковки — это ранее настроенный веб-пакет.

Что ж, многим людям недостаточно просто дважды щелкнуть index.html.

Tip: built files are meant to be served over an HTTP server. Opening index.html over file:// won't work.

Если нужно запустить http сервис, то его можно закинуть в локальные или серверные контейнеры nginx, apache, tomcat и др. для тестирования.Я обычно использую python для запуска http сервиса для запуска (адрес скрипта), естественно, свой IDE также может поддерживать запуск по http.

Междоменное производство

В производственной среде, поскольку внешний и внутренний интерфейсы должны иметь разные порты, чтобы избежать междоменного взаимодействия, прямой/обратный прокси-сервер nginx обычно используется как средство междоменного взаимодействия. (не балансировка нагрузки, две концепции)

server {
        listen       80;
        server_name  localhost;
 
        location ^~ /v1 {
        proxy_pass              https://xiaoce-timeline-api-ms.juejin.im;#代理。
        proxy_set_header        X-Real-IP $remote_addr;#转发客户端真实IP
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        Host $http_host;
        }
 }       

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

Нормализация API

У вас болит голова, чтобы найти интерфейс определенного бизнеса? Вы все еще используете глобальный поиск, чтобы найти собственный интерфейс Вы несколько раз писали определенный интерфейс для разных компонентов? Организуйте свои собственные интерфейсы и аккуратно разделите их, как маршрутизатор выше.

Создайте папку API в /renderer

Добавим в webpack.base.conf.js алиас api, что нам удобно в дальнейшем много звонить

'api': resolve('src/renderer/api')

Мы собираем /renderer/api/juejin.js


import axios from 'axios'

let Api = Function()

Api.prototype = {
    getBlog(page, fn) {
        axios.get(`/v1/getListByLastTime?src=web&pageNum=${page}`).then(res => {
            // if (res.data.code === 200) {
            fn(res.data)
            // }
        }).error()
    }
}
export default new Api()


Измените только что сделанный нами запрос Axios на /blog/index.vue:

  • Сначала представьте API
import juejin from "@/api/juejin";

Обратите внимание на ранее дискретные аксиомы и используйте данные запроса XHR, определенные в API.

getBlog() {
      // this.$http.get("/v1/getListByLastTime?src=web&pageNum=1").then(res => {
      //   this.blogList = res.data.d;
      // });
      juejin.getBlog("1", response => {
        this.blogList = response.d;
      });
    }

Хорошо, многие студенты не понимают, почему простые вещи сложны? На самом деле это не сложно и выглядит очень наглядно: если в большом проекте тысячи запросов, повторение не только приведет к низкому покрытию кода, но и будет выглядеть беспорядочно, что не способствует совместной работе команды. . Эта серия статей познакомит вас с другими методами развития, полезными для команды, и выработает хорошие привычки на основе разделения до и после.

Весь код этой главы находится здесь

обо мне

Прошлые статьи

«Разделение веб-проектов до и после сборки с нуля» Предисловие — Значение открытого исходного кода

«Разделение веб-проектов до и после построения с нуля»: начало — взгляд на историческую эволюцию веба

«Разделение с нуля вокруг веб-проекта» для изучения — до и после подробного разговора об архитектуре разделения

Подготовка к "Разделению веб-проектов до и после сборки с нуля" - Прошли фронтенд? Передовая инфраструктура и внедрение технологий

Битва "Разделение веб-проектов до и после сборки с нуля" - 5 минут для быстрого построения стандартизированного каркаса фронтенд-проекта

«Разделение веб-проектов до и после сборки с нуля» на практике