Достаточно посмотреть на этот сборник понравившийся вам фон + vue + ts + vuecli3.0 + elementUi

Командная строка переводчик Vue.js Vuex
Достаточно посмотреть на этот сборник понравившийся вам фон + vue + ts + vuecli3.0 + elementUi

предисловие

Недавно я попробовал комбинацию vue + ts. Лично мне кажется, что vue не так дружелюбен к ts, как angular2, но я все же выбираю ts между ts и js. С точки зрения синтаксического сахара es6 очень удобен Теперь я подробно расскажу, как использовать ts+vue. Плагинов для ts+vue будет намного меньше, но определенно будет все больше и больше плагинов, так как vue поддерживает tsПревью демо-версии текущего проекта(Как новичок, в конце концов, после многих проектов, я могу дать несколько советов некоторым новичкам (техническое обсуждение группы QQ) 838293023 замечания (github пришел в

Узнайте о плавании фитнес:githubJQ插件 技术文档Техническая документация будет постоянно обновляться


Краткое содержание

  1. Установка vuecli3.
  2. конфигурация конфигурационного файла vue
  3. Создание файла структуры проекта
  4. использование маршрутизации
  5. vue cli запускает и позволяет загружать плагины ts, которые поддерживают vue
  6. Использование ц aixo
  7. Использование vue X
  8. Загрузка изображения (пакетная загрузка) // использование элемента ts
  9. Использование пагинации
  10. Подпакет кнопок переделки
  11. компилятор форматированного текста

1.VueCLI 3.0

VueCLI 3.0Сначала установите node.jsУстановка Baidu самостоятельно

Установить:

# 然后我们安装vuecli3.0 npm 或者 yarn都是可以的网上慢的小伙子可以用yarn
npm install -g @vue/cli
# OR
yarn global add @vue/cli

Создайте проект:

vue create my-project
# OR
vue ui

  1. Первый — это шаблон, который я создал сам.
  2. Второй — системный по умолчанию.
  3. Третья самостоятельная конфигурация

Я создал один здесь, мы выбираем тот, который выделен красным

Мы так выбираем.Если выбран пробел, выберите вверх и вниз

Введите напрямую (по умолчанию согласен)

Введите полностью и выберите package.json, чтобы увидеть, какой ts мы выбрали, а затем проверьте синтаксис sass esl

Затем нажмите Enter, чтобы загрузить окончательный проект cli. Терпеливо ждать

мы скачали

# 输入
vue ui

Добро пожаловать в графический интерфейс vuecli3.0, не волнуйтесь и посмотрите на файловую структуру нашего проекта.

2. Конфигурация файла конфигурации vue


Ниже представлена ​​структура нашего файла

  ##  文件介绍
 
 1.   node_modules //当前node模块存放处
 2.   public //index页面所在镜头文件也可以放这个里面
 3.   src //当前项目存放
        assets //静态文件存放
        components //组件存放
        views //项目存放
        app.vue //这个我们文件的主要路由输入地方
        main //总的js文件
        router //路由文件
        shims-tsx.d //兼容jsx
        shims-vue.d //兼容vue
        store //vuex总文件
 4.   pakeage.js //文件(我们安装的依赖都再里面可以看到,也可以根据这个去下载node_modules)
 5.   我们还少一个vue.config.js 和 pakeage.js 同级
Отправить пользу на нашу вечеринку
// vue.config.js
module.exports = {
    // 选项...
    // 当使用基于 HTML5 history.pushState 的路由时;
    // 当使用 pages 选项构建多页面应用时。
    baseUrl:"",
    // 当运行 vue-cli-service build 时生成的生产环境构建文件的目录。注意目标目录在构建之前会被清除 (构建时传入 --no-clean 可关闭该行为)。
    outputDir:"webApp",
    // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
    assetsDir:"assets",
    // 指定生成的 index.html 的输出路径 (相对于 outputDir)。也可以是一个绝对路径。
    indexPath:"index.html",
    // 默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存。然而,这也要求 index 的 HTML 是被 Vue CLI 自动生成的。如果你无法使用 Vue CLI 生成的 index HTML,你可以通过将这个选项设为 false 来关闭文件名哈希。
    filenameHashing:true,
    // 多页面
    pages:undefined,
    // 编译警告
    lintOnSave:false,
    // 是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。
    runtimeCompiler:false,
    // 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来。
    transpileDependencies:[],
    // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
    productionSourceMap:false,
    // 设置生成的 HTML 中 <link rel="stylesheet"> 和 <script> 标签的 crossorigin 属性。需要注意的是该选项仅影响由 html-webpack-plugin 在构建时注入的标签 - 直接写在模版 (public/index.html) 中的标签不受影响。
    crossorigin:undefined,
    // 在生成的 HTML 中的 <link rel="stylesheet"> 和 <script> 标签上启用 Subresource Integrity (SRI)。如果你构建后的文件是部署在 CDN 上的,启用该选项可以提供额外的安全性。需要注意的是该选项仅影响由 html-webpack-plugin 在构建时注入的标签 - 直接写在模版 (public/index.html) 中的标签不受影响。另外,当启用 SRI 时,preload resource hints 会被禁用,因为 Chrome 的一个 bug 会导致文件被下载两次。
    integrity:false,
    // 反向代理
    devServer:{
        // devServer: {
        //     proxy: {
        //       '/api': {
        //         target: '1',
        //         ws: true,
        //         changeOrigin: true
        //       }
        //     }
        // }
    }
}

Базовая конструкция проекта vue+ts завершена

3. Строительство проекта

Давайте посмотрим на введение проекта после завершения волны (webstormвtsИмпорт не поддерживаетсяvueВсе пациенты с ярко-красным обсессивно-компульсивным расстройством могут использоватьvscodeподдержка была бы лучше)

  public //当前文件
    static //可以放静态资源不会被打包(我放的是富文本编译器的文件后期会太慢可以换成cdn直接引入到index.html)
  src //当前项目文件
    assets //静态资源存放需要被打包
    components //组件存放处
        beforeUpload //单个图片上传组件 (基于element)
        pagination //分页插件 (基于element)
        reset //重置按钮组件
        tinyMceEditor //富文本编译器(这个是重点ts支持的vue插件当前对于我们伸手党来说比较少)
        uploadListImg //批量图片上传(基于element)
        verification //表单验证
    utils //当前项目公用方法
    views //当前项目存放地址
        aixo //当前项目ajax封装
        content //当前项目业务逻辑
        filters //当前项目过滤器
        haveNot //404页面
        layout //项目结构布局
        login //当前项目登陆页面
        method //当前项目的静态遍历存放
        store //当前项目vuex存放(不要为了用vuex而用,其实很多项目都不需要用到vuex的)
        system //权限管理相关
        typings //ts定义使用
        utils //存放其他文件(我这边存了cookie的文件)
    app.vue //全局路由页面
    main.ts //启始的js
    permission.ts //路由中转页面
    route //路由页面
    shims-tsx.d //支持jsx
    shims-vue.d //支持vue
    vue-config //vue配置
    vue-shim.d.ts //声明全局方法(ts会自动抓取.d.ts文件部分全局方法需要定义才可以使用)

Компоненты Компоненты будут объяснены один за другим, а также будут объяснены общедоступные методы.Сначала загрузите те, которые необходимы в данный момент.tsплагин

##   最主要到是这3个
1.   aixo
2.   element
3.   js-cookie

Взгляните на package.js, чтобы увидеть наши текущие зависимости.

Затем идем скачивать текущие зависимости


статьи о благосостоянии

Научит вас, как увидеть, может ли плагин использовать текущий дляvue + tsпроект (текущийts+vueеще меньше)TypeSearch
Если его можно найти, как показано на рисунке ниже, можно в основном судить, что он поддерживает ts


Скачать текущие зависимости проекта

Открываем текущий инструмент управления графикойВыберите, а затем загрузите (также загрузите текущуюtsиз) Вот так весьaixoСкачайте его (все остальные плагины нужно скачать 2)
Второй в основномnode_modulesвнутри@typesЕго можно использовать только после определения внутристраницы маршрутизации иvueРазница страниц не очень большая main.jsне большая разница

app.vueдокумент

говорить об этомvue-property-decoratorИначе вы, ребята, этого не поймете.

### vue-property-decorator
@Prop  父子组件之间传值
   ## 使用方式
   @Prop({
        type: String,
        default: 'Default Value'
    }) msg: string;
    
@Model  数据双向绑定
    @Model('change') checked: boolean
    
@Watch  监听数据变化    
    //监听路由变化
    @Watch('$route')
    onRouteChanged(route: any, oldRoute: any) :void {
        this.$forceUpdate() ## 刷新当前的数据
    }
    
@Provide  提供  /  @Inject  注入   
    ## 父
     @Provide('users')
      users = [
        {
          name: 'test',
          id: 0
        }
      ]
    ## 子  
    @Inject('users') users;  

修饰器
    const Log = (msg) => {
      return createDecorator((component, key) => {
        console.log("#Component", component);
        console.log("#Key", key); //log
        console.log("#Msg", msg); //App
      })
    }
    @Log('fullMessage get called')
    get fullMessage() {
      return `${this.message} from Typescript`
    }

Возможно, вы до сих пор этого не понимаете, я предлагаю вам прочитать официальную документацию.vue-property-decoratorЯ не буду вдаваться в подробности здесь, потому что я относительно глуп (растянуть вечеринку)

Наши проекты всегдаlayoutПосмотрите на этот файл в папке

    layout
        content
            AppMain.vue //当前文件为我们的主要路由
            index.ts //作为我们的总的转接的文件
            navbar.vue //当前项目的左侧导航
            newtab.vue //定义的组件
            prompt,vue //最左侧的结构(先预留起来)
        layout.vue //总项目的文件 
        style.scss //当前项目的css

Смотрите, что мы вводим папку, которая будет автоматически полученаindex.tsпотомindex.tsвes6написание

index.ts

## 新写法ES6 (有时间的老爷可以看下es6)有不懂的可以加群里面直接询问项目结构大概就是这样各位老爷可以github一下即可查看当前代码
    components: {
        Navbar,
        AppMain,
        Prompt
    }
## 老写法   
    components: {
        Navbar: Navbar,
        AppMain: AppMain,
        Prompt: Prompt
    }

2.elementвступление к

1. Сначала установите зависимости

2. Введите css

<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">

3.main.ts представляет глобальные

4. Готов к использованию

скопировать и вставитьelementкод

http://element.eleme.io/#/zh-CN/component/time-picker

Мы должны использовать здесьpublicОбщие переменные, не используйте этоprivateЧастные переменные (следующие переменные не будут найдены в приведенном выше html, хотя об ошибке не будет сообщено)

5. Визуализации

3.aixoиспользование(ajax)

Графический интерфейс для загрузки двух один для совместимостиtsизинкапсулированныйajaxкод

import Axios from 'axios';
import { Message } from 'element-ui';
import { getToken } from '@/views/utils/auth'; // token 不需要可以不要

const httpServer = (opts: any) => {
        const httpDefaultOpts = { // http默认配置
            method: opts.method,
            baseURL: 'https://xxxx.com',  // 测试
            url: opts.url,
            timeout: 100000,
            params: opts.params,
            data: opts.params,
            headers: opts.method == 'get' ? {
            'X-Requested-With': 'XMLHttpRequest',
            'Accept': 'application/json',
            'Content-Type': 'application/json; charset=UTF-8',
            'systoken': '',
            } : {
            'Content-Type': 'application/json;charset=UTF-8' ,
            'systoken': '',
            },
    };
        if (getToken()) {
        const token: any = getToken();
        httpDefaultOpts.headers.systoken = token;
    }
        if (opts.method == 'get') {
        delete httpDefaultOpts.data;
    } else {
        delete httpDefaultOpts.params;
    }
        const promise = new Promise(function(resolve, reject) {
        Axios(httpDefaultOpts).then(
        (res) => {
            if (res.data.code == -3) {
                resolve(res.data);
            } else {
                resolve(res.data);
            }
        },
        ).catch(
        (response) => {
            reject(response);
        },
        );
    });
        return promise;
};

export default httpServer;

import Http from '@/views/aixo/http';

/**
 * 总系统角色菜单 | 根据用户ID获取所属角色的菜单
 * @param userId 用户id
 */
export const managxxxMenuUserId = (userId: any) => {
    return Http({
        url: `/xxx/${userId}`,
        method: 'post',
    });
};

Как использовать

1. Использование vueX (фокус на

Прежде всего, давайте скачаем текущие зависимости на графическом интерфейсе (номер версии и аксиомы должны быть одинаковыми, не знаю, сможем ли мы пойти к нам обоим)Глава ОдинпосмотриСначала создайте 4 файла, я буду говорить об одном файле и еще об одном файле, аудитория будет терпеливо слушать

1.stateфайл (если вы не понимаете, вы можете сначала посмотреть егоvuexОфициальный сайт)

Здесь мы помещаем в него глобальные переменные (скажу, что vuex не используется для vuex, некоторые проекты могут быть совершенно ненужными, конечно)

import { getToken, setToken, removeToken } from '@/views/utils/auth'
const state: any = {
    token: getToken(),
    imgUrl: 'https://api.uat.iyuedian.com/iyd-imall-manage/imall/v1/upload'
}
export default state

2.mutationsдокумент

Этот файл является коммитом для изменения текущегоstateЯ не знаю ценности внутриinterfaceможет видетьМООК

export default mutations{
    ## 老方法
    SET_TOKEN(state: any, data: any) {
         state.token = data
    },
 }
 
import { MutationTree } from 'vuex'
    ## 新方法 MutationTree<any> 相信应该有些人不理就是一个接口
const mutations: MutationTree<any> = {
    'SET_TOKEN'(
        state: any,
        data: any
    ): void {
        state.token = data
    }
}

Вы можете посмотреть исходный код в vuex

3.actionsдокумент

Этот файл можно запуститьmutationsПубличные методы методов в файле могут быть помещены в этотasyncОпределение одношаговой функции всегда фактически возвращает объект Promise.

import { sysUserLogin } from '@/views/interface/login';
import { getToken, setToken, removeToken } from '@/views/utils/auth';
import { ActionTree } from 'vuex';
import { Message } from 'element-ui';

const actions: ActionTree<any, any> = {
    /**
     * 登陆
     * @param param0
     * @param userInfo 登陆信息
     */
    async Login({state, commit} , userInfo: any) {
        return new Promise((resolve, reject) => {
            sysUserLogin(userInfo).then((response: any) => {
              setToken(response.data.systoken);
              console.log(response.data.systoken);
              commit('SET_TOKEN', response.data.systoken); ## 这边调用了上面的方法
              resolve(response);
            }).catch((error) => {
              reject(error);
            });
          });
      },
    /**
     * 深拷贝
     * @param param0
     * @param params
     */
    async deep({state, commit} , params: any) {
      let obj = {};
      obj = JSON.parse(JSON.stringify(params));
      return obj;
    },

};

export default actions;

4.gettersдокумент

gettersможно определить какstoreВычисленное свойство может бытьstateотфильтровать, а затемreturnпублично заявить

## 老方法
export default {
    token: (state:any) => state.token,
}

## 新方法
import {GetterTree} from 'vuex'
const mutations: GetterTree<any,any> = {
    'token'(
        state: any,
    ): any {
        return state.token
    }
}
export default mutations

vuexКак использоватьvuex-class

## 获取state的值 (先要定义一遍才可以使用)
@State imgUrl
@Action('Login') Login;
@Getter('Login') getterFoo;
@Mutation('Login') mutationFoo;
// 简写方式
@State foo
@Getter bar
@Action baz
@Mutation qux
 //最先开始执行 
created() {
    ## 后面的是原来的使用方式
    console.log(this.imgUrl); // ->  this.store.state.imgUrl
    console.log(this.getterFoo(2)) // -> this.store.getters.Login
    this.Login({ value: true }).then() // -> this.store.dispatch('Login', { value: true })
    this.mutationFoo({ value: true }) // -> this.store.commit('Login', { value: true })
}

2. Загрузка изображений (и пакетная загрузка изображений)

Здесь мы используем загрузку изображения элемента, если вы не понимаете, вы можете прочитать этоelements компонент

загрузка одного изображения

Нам нужен лучший и простой способ использования

// 单张图片上传(组件)
<template>
    <div>
        <el-upload
                class="avatar-uploader"
                :action="$store.state.imgUrl" ## 我们图片上传的地址
                :show-file-list="false"
                :on-success="handleAvatarSuccess"
                :before-upload="beforeAvatarUpload">
            <img v-if="BeforeUploadImg" :src="BeforeUploadImg" class="avatar">
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
        </el-upload>
    </div>
</template>

<script lang="ts">

    import { Component, Vue, Model, Watch, Prop } from 'vue-property-decorator';

    @Component
    export default class BeforeUpload extends Vue {

        ## 初始值
        @Prop(String)BeforeUploadImg:string;

        ## 生命周期最先开始执行 void 表示没有返回值
        created():void {
        }

        public handleAvatarSuccess(res:any, file:any) {
            ## 本地图片预览; update: 这样配合父组件可以实现父子组件的双向绑定
            this.$emit('update:BeforeUploadImg',res.data[0].newFileName);
        }
        
        public beforeAvatarUpload(file:any) {
            // const isJPG = file.type === 'image/jpeg';
            const isLt2M = file.size / 1024 / 1024 < 2;
            // if (!isJPG) {
            //     this.$message.error('上传头像图片只能是 JPG 格式!');
            // }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!');
            }
            // return isJPG && isLt2M;
            return isLt2M;
        }
    }
</script>

    # 使用方式
    # html .sync 配合update可以实现双向绑定
    <BeforeUpload :BeforeUploadImg.sync="BeforeUploadImg"></BeforeUpload>
    
    # script
    import BeforeUpload from '@/components/beforeUpload/beforeUpload.vue';
    import { Component, Vue, Model, Watch, Prop } from 'vue-property-decorator';
    @Component({
        components: {
            BeforeUpload,
        }
    })
    export default class Content extends Vue {
        ## 默认图片
        public BeforeUploadImg: string = '';
    }

Массовая загрузка изображений

Нам нужен лучший и простой способ использования

// 批量图片上传(组件)
<template>
    <div>
        <el-upload
                class="upload-demo"
                :action="$store.state.imgUrl"
                :on-preview="handlePreview"
                :on-success="handleOnSuccess"
                :on-remove="handleRemove"
                :file-list="UploadListsImg"
                list-type="picture">
            <el-button size="small" type="primary">点击上传</el-button>
            <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过1024kb</div>
        </el-upload>
    </div>
</template>

<script lang="ts">
    import { Component, Vue, Model, Watch, Prop } from 'vue-property-decorator';

    @Component
    export default class UploadListImg extends Vue {
        // 初始值
        @Prop(null)UploadListsImg:object[];
        //最先开始执行
        created():void {
            // tinyMce.init({})
        }
        /**
         * 删除图片
         * @param file 删除的图片
         * @param fileList 剩下的图片
         */
        public handleRemove(file:any, fileList:any) {
            console.log(file, fileList);
            this.$emit('update:UploadListsImg',fileList)
            this.$emit('removeListImg',file)
        }
        public handlePreview(file:any) {
            console.log(file);
        }

        /**
         * 添加图片
         * @param response 成功的返回值
         * @param file 当前的这个图片
         * @param fileList 当前所有的图片
         */
        public handleOnSuccess(response:any, file:any, fileList:any){
            file.url = response.data[0].newFileName;
            file.name = response.data[0].originalFilename;
            this.$emit('update:UploadListsImg',fileList)
        }

    }
</script>
    ## html UploadListsImg为当前剩下的图片的list    removeListImg为删除掉的list 使用方式
    <UploadListImg :UploadListsImg.sync="UploadListsImg"  @removeListImg="removeListImg" style="width: 400px"></UploadListImg>
    ## script
    import UploadListImg from '@/components/uploadListImg/uploadListImg.vue';
    import { Component, Vue, Model, Watch, Prop } from 'vue-property-decorator';
    @Component({
        components: {
            UploadListImg,
        }
    })
    export default class Content extends Vue {
        public UploadListsImg: object[] = [
            {
                name: 'food.jpeg',
                url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
            },
            {
                name: 'food2.jpeg',
                url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'
            }
        ];
        public removeListImg: object[] = []
    }

3. Использование пейджинга

Разбивка на страницы Нам нужен более простой способ использования

// 分页组件
<style scoped lang="scss">
    .t-pagination{
        width: 100%;
        overflow: hidden;
    }
    .t-pagination-content{
        float: right;
        margin: 20px;
    }
</style>
<template>
    <div class="t-pagination">
        <div class="t-pagination-content">
            <el-pagination
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                :current-page="currentPage4"
                :page-sizes="[10, 20, 30, 40, 100]"
                :page-size="pageSize"
                layout="total, sizes, prev, pager, next, jumper"
                :total="Paginationtotal">
            </el-pagination>
        </div>
    </div>
    
</template>

<script lang="ts">
import Utils from '@/utils/utils'
import { Component, Vue, Model, Prop, Watch } from 'vue-property-decorator';

@Component
export default class Reset extends Vue {
    // props声明
    @Prop() private Paginationtotal!: number;
    private pageSize:number = 20;
    private currentPage4:number = 1;
    //最先开始执行
    created():void {
        if (this.$route.query.pageNum) {
            this.currentPage4 = Number(Utils.deep(this.$route.query.pageNum));
            this.pageSize = Number(Utils.deep(this.$route.query.pageSize));
        }else {
            this.currentPage4 = 1;
            this.pageSize = 20;
        }
    }
    //监听路由变化
    @Watch('$route')
    onRouteChanged(route: any, oldRoute: any) :void {
        if (route.query.pageNum) {
            this.currentPage4 = Number(Utils.deep(route.query.pageNum))
            this.pageSize = Number(Utils.deep(route.query.pageSize));
        }else {
            this.currentPage4 = 1;
            this.pageSize = 20;
        }
        this.$forceUpdate()//强刷当前
    }
    private handleSizeChange(val:any) {
        let data:any = Utils.deep(this.$route.query);
        [data.pageNum,data.pageSize] = [1,val]
        this.start(data)
        console.log(`每页 ${val} re条`);
    }
    private handleCurrentChange(val:any) {
        let data:any = Utils.deep(this.$route.query);
        data.pageNum = val
        data.pageSize = this.pageSize
        this.start(data)
        console.log(`当前页: ${val}re`);
    }
    private start(ret:any) {
        this.$store.dispatch('paramsUrl',ret).then((res:any) => {
            this.$router.push(`${this.$route.path}${res}`)
        })
    }
}
</script>
# html 使用方式
<Pagination :Paginationtotal="Paginationtotal"></Pagination>
# script
import Pagination from '@/components/pagination/pagination.vue';
import { Component, Vue, Model, Watch, Provide } from 'vue-property-decorator';
@Component({
    components: {
        Pagination
    }
})
export default class Content extends Vue {
    Paginationtotal:number = 0;
}

4. Подпакет кнопки переделки

Нам нужно только сбросить текущую страницу пейджинга на первую страницу 20 данных перехода

// 重置按钮
<template>
    <el-button size="mini" @click="reset(searchReserved)">重置</el-button>
</template>

<script lang="ts">
    import { Component, Vue, Model, Prop } from 'vue-property-decorator';

    @Component({
    })
    export default class Reset extends Vue {
        // props声明 paramsUrl 为定义的当前的vuex里面的方法
        @Prop() private searchReserved!:object
        public reset(search:any) {
            [search.pageNum,search.pageSize] = [1,20]
            this.$store.dispatch('paramsUrl',search).then((res:any) => {
                this.$router.push(`${this.$route.path}${res}`)
            })
        }
    }
</script>

## html 使用方式
<Reset :searchReserved="searchReserved"></Reset>
## script
import Reset from '@/components/reset/reset.vue';
@Component({
    components: {
        Reset
    }
})
export default class Content extends Vue {
    searchReserved = {}
}

5. Компилятор форматированного текста

Что касается компилятора форматированного текста, я думаю, что все должны быть знакомы с ним.Я рекомендую корзинуtinyMceиспользовать компилятор форматированного текста в нашем текущем проектеtsПоддержки у всех не так много, я нашел много чего попробовать и наконец решил использоватьtinyMceЗагрузите эти два, наступите на множество ям посередине и дайте нам код, который готов съесть на вечеринке.Быстрее поставить cdn на

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

 ## 富文本编译器 ## EditorContent 默认值 onChangeHandler 改变的事件 editorInit 初始配置 
 ## 基本上图片上传都需要form表单方式上传  FormData
<template>
    <div>
        <Editor :initial-value="EditorContent" @onChange="onChangeHandler" id="tinyMce" :init="editorInit"></Editor>
    </div>
</template>

<script lang="ts">
    import 'tinymce/themes/modern/theme';
    import Editor from '@tinymce/tinymce-vue';
    import { Component, Vue, Model, Watch, Prop } from 'vue-property-decorator';

    @Component({
        components: {
            Editor
        }
    })
    export default class Content extends Vue {
        // 父组件传进来的html
        @Prop(String) EditorContent: any;
        // 初始值
        public initialVal:any = '';
        public editorInit:any = {
            language_url: './static/zh_CN.js',
            language: 'zh_CN',
            selector: 'textarea',
            skin_url: './static/skins/lightgray',
            height: 300,
            // width:600,
            images_upload_url: 'https://api.uat.iyuedian.com/iyd-imall-manage/imall/v1/upload',
            plugins: 'link lists image code table colorpicker textcolor wordcount contextmenu',
            toolbar: 'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat',
            images_upload_handler: function (blobInfo:any, success:any, failure:any) {
                let xhr:any, formData:any;
                xhr = new XMLHttpRequest();
                xhr.withCredentials = false;
                xhr.open('POST', this.$store.state.imgUrl);
                xhr.onload = function() {
                    if(xhr.status<200||xhr.status>=300){
                        failure(xhr.status);
                        return;
                    }
                    let json = JSON.parse(xhr.responseText);
                    if(json.code==0){
                        success(json.data[0].newFileName);
                    } else {
                        failure('HTTP Error: ' + json.msg);
                    }
                };
                formData = new FormData();
                formData.append('file', blobInfo.blob(), blobInfo.filename());
                xhr.send(formData);
            },
            // images_upload_url: 'https://api.iyuedian.com/iyd-imall-manage/imall/v1/upload'
        }
        //最先开始执行
        created():void {
            // tinyMce.init({})
        }
        //监听路由变化
        @Watch('$route')
        onRouteChanged(route: any, oldRoute: any) :void {
            this.$forceUpdate()
        }
        /**
         * 富文本内容变化时事件
         */
        public onChangeHandler(res:any,index:any,tag:any){
            //width height小程序不支持这个把这个替换了
            let html = res.level.content.replace("width","xxx")
            html = html.replace("height","yyy")
            // console.log(html)
            this.$emit('update:EditorContent',html)
        }
    }
</script>
## html 使用方式
<Editor :EditorContent.sync="EditorContent"></Editor>
## script
import Editor from '@/components/tinyMceEditor/tinyMceEditor.vue';
 @Component({
        components: {
            Editor
        }
    })
export default class Content extends Vue {
    // 默认图文详情
    public EditorContent: string = '';
}

1.

Как использовать

резюме

Про основные плагины рассказали.Если есть проблема,можно добавить в вышеуказанную группу qq

Если вы ищете надежный внутренний толчок (район Пекина), вы можете оставить сообщение +. знак равно