仿有赞后台+vue+ts+vuecli3.0+elementUi+四期vueX的使用+图片上传+富文本编译器

栏目: JavaScript · 发布时间: 5年前

内容简介:今天把整个项目剩余都讲完,后面将会学习一下react,然后用react写个后台,然后浅谈一下使用心得,以及学习技巧当前项目demo预览游泳健身了解一下:首先我们先在图形话界面去下载当前需要到依赖(版本号以及axios都需要一致不知道可以去我们都第一章看看

今天把整个项目剩余都讲完,后面将会学习一下react,然后用react写个后台,然后浅谈一下使用心得,以及学习技巧当前项目demo预览

游泳健身了解一下: github JQ插件 技术文档 技术文档会持续更新

内容总结

  1. vueX的使用 //划重点
  2. 图片上传(批量上传)
  3. 分页的使用
  4. 重制按钮的分装
  5. 富文本编译器 //划重点

1.vueX的使用(划重点

首先我们先在图形话界面去下载当前需要到依赖(版本号以及axios都需要一致不知道可以去我们都第一章看看

仿有赞后台+vue+ts+vuecli3.0+elementUi+四期vueX的使用+图片上传+富文本编译器

先建4个文件,我一个文件一个文件讲,观众老爷耐心听

仿有赞后台+vue+ts+vuecli3.0+elementUi+四期vueX的使用+图片上传+富文本编译器

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 里面的源码可以看一下

仿有赞后台+vue+ts+vuecli3.0+elementUi+四期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

仿有赞后台+vue+ts+vuecli3.0+elementUi+四期vueX的使用+图片上传+富文本编译器
## 获取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 下载一下这两个,中间踩了很多坑,给我们伸手党线上开箱即食的代码把

仿有赞后台+vue+ts+vuecli3.0+elementUi+四期vueX的使用+图片上传+富文本编译器

把cdn放上速度更快

仿有赞后台+vue+ts+vuecli3.0+elementUi+四期vueX的使用+图片上传+富文本编译器

重要的说一下我们的静态的这个文件放public 下面这个一定要放这,下面的这个一定要放进去不然页面食用不了 文件链接

仿有赞后台+vue+ts+vuecli3.0+elementUi+四期vueX的使用+图片上传+富文本编译器
## 富文本编译器 ## 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 = '';
}

复制代码

以上所述就是小编给大家介绍的《仿有赞后台+vue+ts+vuecli3.0+elementUi+四期vueX的使用+图片上传+富文本编译器》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

平台革命:改变世界的商业模式

平台革命:改变世界的商业模式

[美]杰奥夫雷G.帕克(Geoffrey G. Parker)、马歇尔W.范·埃尔斯泰恩(Marshall W. Van Alstyne)、桑基特·保罗·邱达利(Sangeet Paul Choudary) / 志鹏 / 机械工业出版社 / 2017-10 / 65.00

《平台革命》一书从网络效应、平台的体系结构、颠覆市场、平台上线、盈利模式、平台开放的标准、平台治理、平台的衡量指标、平台战略、平台监管的10个视角,清晰地为读者提供了平台模式最权威的指导。 硅谷著名投资人马克·安德森曾经说过:“软件正在吞食整个世界。”而《平台革命》进一步指出:“平台正在吞食整个世界”。以平台为导向的经济变革为社会和商业机构创造了巨大的价值,包括创造财富、增长、满足人类的需求......一起来看看 《平台革命:改变世界的商业模式》 这本书的介绍吧!

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具