仿有贊後臺+vue+ts+vuecli3.0+elementUi 集合看這篇就夠了

前言

最近嘗試了vue+ts的組合我的感受vue對於ts並無特別的像angular2這樣的友好,可是對於ts和js之間我的仍是選擇ts的。語法糖來講es6簡直舒爽,下面我詳細介紹下怎麼使用ts+vue。ts+vue的插件會少上不少,可是確定會隨着vue對ts的支持插件也會愈來愈多當前項目demo預覽(做爲一個菜雞畢竟經歷衆多項目能夠給一些新手一點提示 (QQ羣技術討論)838293023備註(github進來的css

游泳健身瞭解一下:githubJQ插件 技術文檔 技術文檔會持續更新html


內容總結

  1. vue cli3的安裝。
  2. vue config文件配置
  3. 項目結構文件搭建
  4. 路由的使用
  5. vue cli啓動以及啓用下載ts 支持vue 的插件
  6. ts aixo的使用
  7. vue X的使用
  8. 圖片上傳(批量上傳)//ts element的使用
  9. 分頁的使用
  10. 重製按鈕的分裝
  11. 富文本編譯器

1.VueCLI 3.0

VueCLI 3.0 首先安裝node.js本身百度安裝vue

安裝:node

# 而後咱們安裝vuecli3.0 npm 或者 yarn都是能夠的網上慢的小夥子能夠用yarn
npm install -g @vue/cli
# OR
yarn global add @vue/cli
複製代碼

建立一個項目:webpack

vue create my-project
# OR
vue ui
複製代碼

  1. 第一個是本身建立過的模版。
  2. 第二個是系統默認的
  3. 第三個本身選配置
    我這邊有建立過一個,咱們選紅色選中的這個

咱們這樣選擇。空格鍵是否選中,上下選擇ios

直接回車(默認贊成)git

一路回車而後選擇package.json 看下咱們選擇了啥ts 而後sass 語法檢查esles6

而後再回車就進行最後的cli項目的下載了。耐心等待github

咱們下載好了web

# 輸入
vue ui
複製代碼

歡迎來到vuecli3.0 圖形話界面,現彆着急現看咱們的項目文件結構

2.vue config文件配置


下面是咱們的文件的結構

## 文件介紹
 
 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的使用(劃重點

首先咱們先在圖形話界面去下載當前須要到依賴(版本號以及axios都須要一致不知道能夠去咱們都第一章看看

先建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.圖片上傳(以及批量的圖片上傳

這裏咱們用的是element的圖片上傳 若有不懂的能夠看下element的組件

單張圖片上傳

咱們想要更佳簡便的使用方式

// 單張圖片上傳(組件)
<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放上速度更快

重要的說一下咱們的靜態的這個文件放public 下面這個必定要放這,下面的這個必定要放進去否則頁面食用不了文件連接

## 富文本編譯器 ## 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羣

求靠譜內推(北京地區)能夠留言我 +。=

相關文章
相關標籤/搜索