前言
今天把整個專案剩餘都講完,後面將會學習一下react,然後用react寫個後臺,然後淺談一下使用心得,以及學習技巧 當前專案demo預覽
內容總結
- vueX的使用 //劃重點
- 圖片上傳(批量上傳)
- 分頁的使用
- 重製按鈕的分裝
- 富文字編譯器 //劃重點
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
下載一下這兩個,中間踩了很多坑,給我們伸手黨線上開箱即食的程式碼把
重要的說一下我們的靜態的這個檔案放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群
後面的章節介紹
- 表單驗證 (基礎表單驗證)
- react 會自己寫完然後講解一下