Эта статья участвовала в "Проект «Звезда раскопок»”, чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.
Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность.
предисловие
- онлайн музыкаТкни меня!
- Исходный код музыкального блогаСейчас в сети!
- Я организовывал свои собственныеонлайн музыка(Поскольку сервер был недавно изменен), я обнаружил, что загруженные файлы изображений очень беспорядочны, например: музыка загружается на минио (файловый сервер), изображения модуля ИТ-знаний загружаются в папку, указанную Node , а файлы других модулей находятся в другой папке Node.
- Я думал о том, можно ли управлять всеми этими файлами одному, и я сначала подумал, что компания (dpf) построила файловый сервер во время моей предыдущей стажировки, и им было действительно удобно пользоваться, то есть сегодняшний главный герой -- Минио.
- На самом деле, собственныйонлайн музыкаОн давно используется, но не сказано, что все файлы им управляются, а сейчас приложение развернуто на Docker, не знаю, почему Node постоянно не мапится, но Minio умеет мапить. Все помещаются в минио.
- Далее я поделюсь, как его собрать, и проблемами, с которыми можно столкнуться, которые будут выпускаться одна за другой.
- Вы готовы?
счастливый отпуск.
Сначала сделаем снимок.
Интерфейс интуитивно понятный, визуальный интерфейс, удобное управление, простой процесс загрузки и выгрузки, а также можно установить разрешения, время истечения срока действия и т. Д.
Minio
-
что
-
Как скачать, установить и использовать
-
Как разрабатывать на уровне кода
1. Что такое Минио?
Minio — это служба хранения объектов, основанная на протоколе с открытым исходным кодом Apache License v2.0. Он совместим с интерфейсом службы облачного хранилища Amazon S3 и очень подходит для хранения неструктурированных данных большой емкости, таких как изображения, видео, файлы журналов, данные резервного копирования и образы контейнеров/виртуальных машин и т. д. Объектный файл может иметь любой размер. размер, от нескольких килобайт до максимального диапазона 5T.
MinIO — это очень легкий сервис, который можно легко интегрировать с другими приложениями, такими как NodeJS, Redis или MySQL.
Он также поддерживает интегрированную разработку клиентов на нескольких языках, таких какJavaScript 、Java、Python、Golang、.NET
.
В двух словах:файловый сервер, для хранения и управления нашими файлами.
2. Как загрузить, установить и использовать Minio?
Мы берем среду окна и докера для практического обучения. В настоящее время эти две среды больше используются людьми. (😁 На самом деле я использую только эти две среды, а другие среды не смеют говорить)
2.1 версия для Windows
2.1.1 Скачать
-
Программное обеспечение для загрузки облака Baidu: ссылка:Disk.Baidu.com/Yes/1Pop-All w4Q…Код извлечения: n5le
После скачивания расширение файла exe.
2.1.2 Использование
Введите каталог, в котором находится файл minio.exe.
cmd подходит.
minio.exe server G:\tsblog\minio
Параметр Описание:G:\tsblog\minio
Это директория хранения после загрузки файла (куда загружаются наши картинки)
Запустить успешно. Вы увидите следующий интерфейс.
Здесь minio выдаст ACCESS-KEY и SECRET-KEY для фонового входа в систему.
2.1.3 Вход и использование
Откройте браузер и используйте адрес, указанный в интерфейсе командной строки, для входа в систему.
Порт по умолчанию 9000:http://localhost:9000/
Введите КЛЮЧ ДОСТУПА и СЕКРЕТНЫЙ КЛЮЧ, чтобы войти в интерфейс управления minio.
2.1.4 Создайте корзину и загрузите изображения
В интерфейсе управления фоном можно создать свой Bucket (ведро), под которым можно понимать папку для хранения картинок. После успешного создания корзины вы можете загружать изображения. Как показано ниже:
Слева ведро (папка) и справа файлы в ведре.
В правой части списка файлов вы можете скопировать адрес доступа к изображению, и вы можете получить доступ к изображению в браузере. Адрес изображения в это время имеет срок действия и ключ.
2.2 Докер-версия
Мы развернем minio онлайн.Как мы все знаем, большинство серверов — это системы Linux, и у меня также установлен Docker для управления моими приложениями.
2.2.1 Загрузите пакет образа MinIO
docker pull minio/minio
2.2.2 Запустите образ MinIO
использоватьdocker run -p 9000:9000 minio/minio server /data
Порт можно настроить и изменить. По умолчанию будут сгенерированы ACCESS_KEY и SECRET_KEY. См. рисунок ниже, чтобы показать, что сгенерированныйminioadmin/minioadmin
Конечно, обычно мы так не начинаем, и мы должны настроить пароль учетной записи. Также сопоставьте файл minio (это важно)
Используйте следующий сценарий, чтобы запустить образ MinIO для создания постоянного контейнера MinIO.
Как правило, копирование этой строки кода подходит для большинства случаев.
docker run -p 9000:9000 --name minio -d
-e "MINIO_ACCESS_KEY=admin"
-e "MINIO_SECRET_KEY=123456"
-v /home/minio:/data
-v /home/minio/config:/root/.minio
minio/minio server /data
Параметр Описание
-
запустить: запустить образ
-
-p 9000:9000: Установить порт и сопоставить его с внешним портом
-
-d: запустить в фоновом режиме
-
-e "MINIO_ACCESS_KEY=admin" -e "MINIO_SECRET_KEY=123456" : Установить пароль учетной записи (MINIO_ACCESS_KEY: ключ пароля; MINIO_SECRET_KEY: значение пароля)
-
-v /home/minio:/data -v /home/minio/config:/root/.minio : виртуальный каталог конфигурации, файлы отображаются, ресурсы моей папки minio помещаются в /home/minio/, если вы хотите изменить Если да, измените путь здесь
-
сервер minio/minio: это имя образа minio, который мы извлекли с самого начала.
Некоторые ребята не знают, что означает сопоставление файлов, позвольте мне проанализировать это.
Разворачиваем minio для запуска в докере.
Например, если мы загружаем файл в minio, как нам проверить, где этот файл находится на сервере linux?
В настоящее время сопоставление файлов необходимо.С точки зрения непрофессионала, файлы, загруженные в minio, сопоставляются с linux, чтобы мы могли видеть загруженные файлы в реальном времени в linux.
2.2.3 Просмотр образа MinIO
Проверьте, успешно ли запущен minio:docker ps
Клиент входа в систему также может успешно войти в систему!
3. Минио бой (как развивать на уровне кода)
Мы знаем, что MinIO — это очень легкий сервис, который может поддерживать интегрированную разработку клиентов на нескольких языках, таких какJavaScript 、Java、Python、Golang、.NET
.
Мы берем JavaScript и Java для практического обучения. В настоящее время эти две среды больше используются людьми. (😁 На самом деле я использую только эти две среды, и мы не смеем говорить на других языках)
3.1 JavaScript представляет minio и использует его
онлайн музыкаФайл модуля [ИТ-знания] в файле изначально загружается узлом и сохраняется на сервере локально, но позже я хочу управлять всеми файлами унифицированным образом и загрузить их в minio несколько дней назад.
В этом примере в качестве бэкенда JavaScript используется koa2.
3.1.1 koa2 установить минио
npm i minio --save-dev
3.1.2 Создайте новый файл minio.js
Настройте порт пароля учетной записи minio.
var Minio = require("minio");
let endPoint = "127.0.0.1";
var minioClient = new Minio.Client({
endPoint,
port: 9000,
useSSL: false,
accessKey: "admin",
secretKey: "123456",
});
module.exports = minioClient;
Таким образом, вы можете начать использовать minio в интерфейсе js.Конечно, вам нужно импортировать файл minio.js, определенный выше, прежде чем писать.
Ниже перечислены несколько часто используемых методов.
3.1.3 Список всех сегментов (папок)
minioClient.listBuckets().then((res) => {
console.log(res);
})
3.1.4 Список всех файлов в сегменте
var stream = minioClient.listObjectsV2("music", "", true);
let arr = [];
stream.on("data", (obj) => {
arr.push(obj); // 每一个文件都会去执行该data方法,类似于遍历
});
stream.on("end", function () {
console.log(arr);
// 全部遍历完成后,在这里会打印出该music文件夹下的所有文件
});
stream.on("error", function (err) {
console.log(err);
});
3.1.5 Определить, есть ли это ведро
minioClient.bucketExists("music", function (err, exists) {
if (err) {
console.log(err);
}
if (exists) {
console.log('存在')
} else {
console.log('不存在')
}
});
3.1.6 Создание нового сегмента
minioClient.makeBucket("music", "us-east-1", function (err) {
if (err) {
console.log("Error creating bucket.", err);
}
console.log('创建成功')
});
3.1.7 Загрузка объекта и сохранение его в виде файла в локальной файловой системе
minioClient.fGetObject(
"music",
"周杰伦 - Mojito202006152354441192.flac",
"H:/85/周杰伦 - Mojito202006152354441192.flac",
function (err) {
if (err) {
console.log(err);
}
console.log('下载成功');
}
);
3.1.8 Временный URL для скачивания
minioClient.presignedUrl("GET", "music", "周.flac", 24 * 60 * 60, function (
err,
presignedUrl
) {
if (err) {
console.log(err);
}
console.log(presignedUrl);
});
3.1.9 Загрузить файл в корзину
При загрузке файлов помните, что имя файла может повторяться, поэтому здесь в качестве имени файла добавляется случайное число;
Конечно, все правила устанавливаются людьми, и вы можете сформулировать различные методы письма в соответствии со своей сценой;
Вы можете видеть, что поля, напечатанные в функции minioClient.putObject(), обычно существуют в базе данных.
const bucketsName = "music", file = File对象;
const path = file[0][1].path;
const fileName = file[0][1].name;
const type = file[0][1].type;
const nowDate = moment(new Date()).format("YYYYMMDDHHmmss");
const random = Math.round((Math.random() * 9 + 1) * 1000);
const fileNameRandom = nowDate + random;
const fileSuffix = fileName.substring(fileName.lastIndexOf(".")); // 文件后缀名字
const filePrefix = fileName.substring(0, fileName.lastIndexOf(".")); // 文件名字前面那段
let objectName = filePrefix.length > 20
? filePrefix.substring(0, 20) + fileNameRandom + fileSuffix
: filePrefix + fileNameRandom + fileSuffix;
var fileStream = fs.createReadStream(path);
fs.stat(path, function (err, stats) {
if (err) {
console.log(err);
}
minioClient.putObject(
bucketsName,
objectName,
fileStream,
stats.size,
{ "Content-Type": type },
function (err, etag) {
if (err) {
console.log(err);
}
console.log({
fileName,
bucketsName,
fileContentType: type,
size: stats.size,
fileNameRandom,
url: objectName,
});
}
);
});
});
3.1.10 Получить информацию о файле
minioClient.statObject("test", '9.png', function (err, stat) {
if (err) {
console.log(err);
}
console.log(stat);
});
3.1.11 Удаление объекта
minioClient.removeObject("test", '9.png', function (e) {
if (e) {
console.log("Unable to remove Objects ", e);
}
console.log('移除成功');
});
3.1.12 Удалить все объекты из списка объектов
minioClient.removeObjects("test", ['9.png'], function (e) {
if (e) {
console.log("Unable to remove Objects ", e);
}
console.log('移除成功');
});
Я написал класс минио-инструментов на github, ленивые люди могут у него поучиться (поставьте ⭐звезду, если можете):GitHub.com/git-достоинство…
В официальной документации minio также есть наглядные примеры работы:docs.min.io/docs/java удалить…
3.2 Java представляет minio и использует его
онлайн музыкаФайл модуля [Музыка] в файле всегда управлялся minio.
Фактически, метод написания java и JavaScript в основном одинаков.
Почти такой же.
3.2.1 мини-установка java
Файл pom.xml вводит зависимости
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>3.0.10</version>
</dependency>
3.2.2 в application.yml
Мне нравится записывать параметры конфигурации (пароль учетной записи) в файл application.yml для стандартизированного управления.
#文件服务器
minio:
endpoint: http://39.108.185.253 # 外网
accessKey: admin
secretKey: 123456
endpointIn: http://127.0.0.1:9000 # 内网
3.2.3 Создание класса сущностей Minio.java
package com.example.bkapi.common.entity;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "minio")
public class Minio {
private String endpoint;
private String accessKey;
private String secretKey;
private String endpointIn;
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public String getSecretKey() {
return secretKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public String getEndpointIn() {
return endpointIn;
}
public void setEndpointIn(String endpointIn) {
this.endpointIn = endpointIn;
}
}
Таким образом, вы можете начать использовать minio в интерфейсе.Конечно, вам нужно представить класс сущности Minio, определенный выше, прежде чем писать.
private static Minio minio;
Ниже перечислены несколько часто используемых методов.
3.2.4 Создание миниклиента
Написано здесь на самом деле то же самое, что и выше3.1.2 Создайте новый файл minio.jsто же самое, чтобы создать экземпляр Minio.
следующееminio.getEndpoint()
Получите определение, определенное в application.ymlhttp://39.108.185.253
следующееminio.getAccessKey()
Получите определение, определенное в application.ymladmin
следующееminio.getSecretKey()
Получите определение, определенное в application.yml123456
Здесь могут быть записаны любые параметры, в зависимости от личных привычек.
public static MinioClient createMinioClient() throws InvalidPortException, InvalidEndpointException {
MinioClient minioClient = new MinioClient(minio.getEndpoint(), minio.getAccessKey(), minio.getSecretKey());
return minioClient;
}
3.2.5 Создание minioClient для интрасети
следующееminio.getEndpoint()
Получите определение, определенное в application.ymlhttp://127.0.0.1:9000
другие параметры и вышеcreateMinioClient
Так же.
public static MinioClient createInMinioClient() throws InvalidPortException, InvalidEndpointException {
MinioClient minioClient = new MinioClient(minio.getEndpointIn(), minio.getAccessKey(), minio.getSecretKey());
return minioClient;
}
3.2.6 Создать новую корзину с заданным регионом
Сначала определите, существует ли это ведро и не создается ли новое ведро.
public static void makeBucket(String bucketName){
try {
MinioClient minioClient = createInMinioClient();
// Create bucket if it doesn't exist.
boolean found = minioClient.bucketExists(bucketName);
if (found) {
System.out.println(bucketName + " already exists");
} else {
// Create bucket 'my-bucketname'.
minioClient.makeBucket(bucketName);
System.out.println(bucketName + " is created successfully");
}
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
}
3.2.7 Список всех сегментов
public static List<Bucket> listBuckets(){
List<Bucket> bucketList = null;
try {
MinioClient minioClient = createInMinioClient();
// List buckets that have read access.
bucketList = minioClient.listBuckets();
for (Bucket bucket : bucketList) {
System.out.println(bucket.creationDate() + ", " + bucket.name());
}
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return bucketList;
}
3.2.8 Проверка существования корзины
public static boolean bucketExists(String bucketName){
boolean found = false;
try {
MinioClient minioClient = createInMinioClient();
// Check whether 'my-bucketname' exists or not.
found = minioClient.bucketExists(bucketName);
if (found) {
System.out.println(bucketName + " exists");
} else {
System.out.println(bucketName + " does not exist");
}
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return found;
}
3.2.9 Удаление корзины
Сначала определите, существует ли ведро, и удалите его, если оно существует.
Примечание: - removeBucket не удаляет объекты внутри корзины. Объекты необходимо удалять с помощью API removeObject.
public static void removeBucket (String bucketName){
try {
MinioClient minioClient = createInMinioClient();
// Check if my-bucket exists before removing it.
boolean found = minioClient.bucketExists(bucketName);
if (found) {
// Remove bucket my-bucketname. This operation will succeed only if the bucket is empty.
minioClient.removeBucket(bucketName);
System.out.println(bucketName + " is removed successfully");
} else {
System.out.println(bucketName + " does not exist");
}
} catch(MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
}
3.2.10 Список информации об объекте в данном сегменте
Сначала определите, существует ли ведро или нет, и перечислите информацию об объекте в данном ведре, если оно существует.
public static Iterable<Result<Item>> listObjects(String bucketName){
Iterable<Result<Item>> myObjects = null;
try {
MinioClient minioClient = createInMinioClient();
// Check whether 'mybucket' exists or not.
boolean found = minioClient.bucketExists(bucketName);
if (found) {
// List objects from 'my-bucketname'
myObjects = minioClient.listObjects(bucketName);
for (Result<Item> result : myObjects) {
Item item = result.get();
System.out.println(item.lastModified() + ", " + item.size() + ", " + item.objectName());
}
} else {
System.out.println(bucketName + " does not exist");
}
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return myObjects;
}
3.2.11 Список информации об объекте в заданном сегменте и префиксе
Сначала определите, существует ли ведро, и если оно существует, перечислите информацию об объекте в данном ведре и префиксе.
public static Iterable<Result<Item>> listObjects(String bucketName,String prefix){
Iterable<Result<Item>> myObjects = null;
try {
MinioClient minioClient = createInMinioClient();
// Check whether 'mybucket' exists or not.
boolean found = minioClient.bucketExists(bucketName);
if (found) {
// List objects from 'my-bucketname'
myObjects = minioClient.listObjects(bucketName,prefix);
for (Result<Item> result : myObjects) {
Item item = result.get();
System.out.println(item.lastModified() + ", " + item.size() + ", " + item.objectName());
}
} else {
System.out.println(bucketName + " does not exist");
}
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return myObjects;
}
3.2.12 Перечислите информацию об объекте как Iterable в данной корзине, префиксе и флаге рекурсии
public static Iterable<Result<Item>> listObjects(String bucketName, String prefix, boolean recursive){
Iterable<Result<Item>> myObjects = null;
try {
MinioClient minioClient = createInMinioClient();
// Check whether 'mybucket' exists or not.
boolean found = minioClient.bucketExists(bucketName);
if (found) {
// List objects from 'my-bucketname'
myObjects = minioClient.listObjects(bucketName,prefix,recursive);
for (Result<Item> result : myObjects) {
Item item = result.get();
System.out.println(item.lastModified() + ", " + item.size() + ", " + item.objectName());
}
} else {
System.out.println(bucketName + " does not exist");
}
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return myObjects;
}
3.2.13 Загрузка объектов в виде потоков
public static InputStream getObject(String bucketName, String objectName){
InputStream stream = null;
try {
MinioClient minioClient = createInMinioClient();
// Check whether the object exists using statObject().
// If the object is not found, statObject() throws an exception,
// else it means that the object exists.
// Execution is successful.
minioClient.statObject(bucketName, objectName);
// Get input stream to have content of 'my-objectname' from 'my-bucketname'
stream = minioClient.getObject(bucketName, objectName);
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return stream;
}
3.2.14 Загрузка и сохранение объектов в виде файлов в локальной файловой системе
public static void getObject(String bucketName, String objectName, String fileName){
try {
MinioClient minioClient = createInMinioClient();
// Check whether the object exists using statObject().
// If the object is not found, statObject() throws an exception,
// else it means that the object exists.
// Execution is successful.
minioClient.statObject(bucketName, objectName);
// Gets the object's data and stores it in photo.jpg
minioClient.getObject(bucketName, objectName, fileName);
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
}
3.2.15 Загрузка объектов через InputStream
public static ObjectStat putObject(String bucketName, String objectName, InputStream stream, long size, String contentType){
try {
MinioClient minioClient = createInMinioClient();
// 创建对象
minioClient.putObject(bucketName, objectName, stream, size, contentType);
System.out.println(objectName + " is uploaded successfully");
} catch(MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return statObject(bucketName,objectName);
}
3.2.16 Загрузка в объект через файл
public static int putObject(String bucketName, String objectName, String fileName){
try {
MinioClient minioClient = createInMinioClient();
minioClient.putObject(bucketName, objectName, fileName);
System.out.println(objectName + " is uploaded successfully");
} catch(MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return 1;
}
3.2.17 Копировать данные из объекта, указанного в objectName, в объект, указанный в destObjectName.
public static void copyObject(String bucketName, String objectName, String destBucketName, String destObjectName, CopyConditions cpConds, Map<String, String> metadata){
try {
MinioClient minioClient = createInMinioClient();
CopyConditions copyConditions = new CopyConditions();
copyConditions.setMatchETagNone("TestETag");
minioClient.copyObject(bucketName, objectName, destBucketName, destObjectName, copyConditions);//copyConditions 或 cpConds
System.out.println(objectName + " is uploaded successfully");
} catch(MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
}
3.2.18 Удаление объекта
public static void removeObject(String bucketName, String objectName){
try {
MinioClient minioClient = createInMinioClient();
// 从bucketName中删除objectName。
minioClient.removeObject(bucketName, objectName);
System.out.println("successfully removed " + bucketName + "/" +objectName);
} catch (MinioException e) {
System.out.println("Error: " + e);
} catch (Exception e) {
e.printStackTrace();
}
}
3.2.19 Удалить несколько объектов
public static Iterable<Result<DeleteError>> removeObject(String bucketName, Iterable<String> objectNames){
Iterable<Result<DeleteError>> results = null;
try {
MinioClient minioClient = createInMinioClient();
// 删除my-bucketname里的多个对象
results = minioClient.removeObject(bucketName, objectNames);
for (Result<DeleteError> errorResult: results) {
DeleteError error = errorResult.get();
System.out.println("Failed to remove '" + error.objectName() + "'. Error:" + error.message());
}
} catch (MinioException e) {
System.out.println("Error: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return results;
}
3.2.20 Получить постоянный адрес файла
public static String getObjectUrl(String bucketName, String objectName){
String url = null;
try {
MinioClient minioClient = createInMinioClient();
url = minioClient.getObjectUrl(bucketName, objectName);
System.out.println(url);
} catch(MinioException e) {
System.out.println("Error occurred: " + e);
} catch (Exception e) {
e.printStackTrace();
}
return url;
}
Я написал класс минио-инструментов на github, ленивые люди могут у него поучиться (поставьте ⭐звезду, если можете):GitHub.com/git-достоинство…
В официальной документации minio также есть наглядные примеры работы:docs.min.io/docs/java — из...
Наконец
На прошлой неделе университетские тираны пришли посидеть, поболтать и увидели, как я занимаюсьонлайн музыка, Говоря о файлах в проекте, которыми я намереваюсь управлять с помощью minio, я спросил его, как управляются файлы, а также папка, указанная серверной частью загрузки.
Поэтому я открыл минио, чтобы показать ему. Сначала я подумал, что это просто визуальный интерфейс. Я сказал, что есть еще такие функции, как истечение срока действия файлов и разрешения. О ~ Там тоже есть эти функции.
Если это полезно для вас, ваши лайки - это смазка для меня, чтобы двигаться вперед.
Связанная литература
Установка и использование Minio Windows
Предварительное исследование развертывания MinIO Docker
Рекомендовано в прошлом
Ты да сказал, что все мои коды не добавляют точки с запятой
Все, что сказал Лао Ши, является объектом, вы верите в это?
Vue-Cli3 создает библиотеку компонентов
Vue реализует динамическую маршрутизацию (и интервьюер выдает основные моменты проекта)
Операция Axios, которую вы не знаете в проекте (рукописные основные принципы, совместимость)
Документация по компонентам проекта сборки VuePress
система управления фоном vue-typescript-admin-template