生活随笔
收集整理的這篇文章主要介紹了
Vue, App与我(十三)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Vue, App與我(十三)
前言:
- Big-man需要開發一個論壇模塊, 論壇模塊的話,簡而言之, 就是一個發帖和回帖的模塊。但是Big-man的這個論壇模塊還是比較復雜的。在接下來的實現中Big-man會進一步地去進行分析。所以Big-man懷著好奇的心態進入了移動端的論壇模塊。
首頁:
- 從這個首頁的設計圖上就可以得出, 需求是多么地繁雜,特別是涉及到圖片上傳這一塊,原來的頭像更換代碼, 也是相當于圖片上傳。代碼如下:
<template><
div><
div class=
"navTop"><i
class=
"iconfont back" onclick=
"javascript:history.go(-1)">&<span
class=
"navCon">圖片</span><span
class=
"publish" v-
on:click=
"updateUser()" style=
"display:none;">保存</span></
div><
div class=
"ask pt45"><
div class=
"tips"><p
class=
"tips_title">修改圖片</p> </
div><
div class=
"text"><
div id=
"app"><img
id=
"picture_sourceimg" :src=
"picture" width=
"600" height=
"800"><input type=
"hidden" id=
"picture" name=
"picture" value=
"picture" ref=
"picture"> <
div class=
"weui_uploader_input_wrp" v-
on:click=
"changeUpload()"></
div></
div></
div></
div></
div>
</template>
- <input type="hidden" id="picture" name="picture" value="picture" ref="picture">
- input 標簽代碼中的type=hidden是定義隱藏的字段,這里這樣寫主要是想要通過樣式實現如下的效果:
- 查看如下的樣式修飾代碼:
<style scoped>
.navTop .publish{ height:0.45rem; padding-right:0.15rem; color:#ffffff; font-size:0.15rem; line-height:0.45rem;}
.pt45{ padding-top:0.45rem; overflow:hidden;}
.ask{ overflow:hidden; }
.ask .text{ overflow:hidden; padding:0.15rem;}
.ask .text textarea{ width:90%; padding:5%; overflow:hidden; border:none; outline:none; background:#ffffff;}
.ask .tips{ padding:0 0.15rem; overflow:hidden; color:#a5a5a5; font-size:0.12rem;background-color: #E8E5E5;padding-bottom:0.15rem;}
.tips .tips_title{font-size:20px;font-weight:500;padding-top:0.15rem;color:#000000}
ul { list-style: none outside none; margin:0; padding: 0; }
li { margin: 0 10px; display: inline; }
#app{overflow: hidden;text-align: center;}
img {overflow: hidden; width: 150px;height:150px; border-radius: 150px; border: 1px solid #284baa; margin: auto;float: left;display: inline;margin-bottom: 10px;}
.weui_uploader_input_wrp {float: right;position: relative;margin-right: 9px;margin-bottom: 9px;width: 77px; height: 77px;border: 1px solid #d9d9d9;}
.weui_uploader_input_wrp:before {width: 2px;height: 39.5px;}
.weui_uploader_input_wrp:after {width: 39.5px;height: 2px;}
.weui_uploader_input_wrp:before {content: " ";position: absolute;top: 50%;left: 50%;-webkit-transform: translate(-50%,-50%);transform: translate(-50%,-50%);background-color: #d9d9d9;}
.weui_uploader_input_wrp:after, .weui_uploader_input_wrp:before {content: " ";position: absolute; top: 50%;left: 50%;-webkit-transform: translate(-50%,-50%);transform: translate(-50%,-50%);background-color: #d9d9d9;}
.weui_uploader_input {position: absolute;z-index: 1;top: 0;left: 0;width: 100%;height: 100%;opacity: 0;-webkit-tap-highlight-color: rgba(0,0,0,0);}
.weui_uploader_file {float: left; margin-right: 9px;margin-bottom: 9px;width: 79px;height: 79px;background: no-repeat 50%;background-size: cover;}
#picture_uploadimg{float: right;}
.photoclose {position: absolute;display: block;right: 0;top: 0;margin: 2px 2px 0 0;width: 23px;background: #fff;}
.photoshow {display: block;float: left;position: relative;margin-right: 8px;margin-top: 8px;overflow: hidden;zoom: 1;}.contain {width:100%; height:300px;border:1px solid #ccc;}
</style>
<script>
import Error from
'../components/Error.vue'
import Tab from
'../components/Tab.vue'
import Config from
'../config.js'
import {Toast} from
'mint-ui'
import Store from
'../store.js'export default {
components: {Error,Tab},data () {
return {
isError:
false,
error:
'',
picture:
'',
whoami:
'user/whoami/',
govUrl:
'user/update/'}},
beforeMount:
function(){
if(Store.getAuthUid()){
this.$http.get(
this.whoami,{}).
then((response) => {const ret = JSON.parse(response.data);if(ret && ret['code'] === 0){if(!ret['picture']){if(ret['wx_picture']){this.picture = ret['wx_picture']}else{this.picture = Config.defaultPic}}else{this.picture = Config.baseUrl + ret['picture']}}else{this.$router.push('/login')return}})}else{this.$router.push('/login')return}},methods: {fullUrl: function(url) {return Config.baseUrl + url},defaultPicUrl:function(){return Config.defaultPic},changeUpload:function(e){var share = {action: 'uploadImage',Authorization: 'Xyapp ' + Store.getAuthUid(),api: '/user/upload/'}if(window.postMessage) window.postMessage(JSON.stringify(share),'*');return true},updateUser: function(){var picture = this.$refs.picture.valuethis.getUpdate(picture)},getUpdate(picture) {this.$http.post(this.govUrl,{picture:picture} ).then( (response) => {const ret = JSON.parse(response.data || "[]")if(ret && ret.code === 0){Toast('操作成功!')this.$router.push('/userset')}else{Toast(ret.msg)this.error = (ret && ret.msg) || ""this.isError = true}},(response) => {this.isError = truethis.error = ""if(callback) callback.call(this)});}}
}
</script>
- changeUpload()函數事件也就是圖片的加載事件, 具體代碼如下:
changeUpload:
function(e){var share = {action:
'uploadImage',Authorization:
'Xyapp ' + Store.getAuthUid(),api:
'/user/upload/'}
if(window.postMessage) window.postMessage(
JSON.stringify(share),
'*');
return true
},
- 在以上的代碼中, Big-man在書寫的時候還犯了一個致命的錯誤,且這個錯誤是因為Big-man的經驗不足造成的,比如如下的代碼:
- Authorization: 'Xyapp ' + Store.getAuthUid(),
- Authorization: 'Xyapp' + Store.getAuthUid(),
- 這兩段代碼大家可以仔細的推敲一下,在Big-man的書寫過程當中就犯了這個錯誤,由此分享出來以供大家參考,引以為戒。
- 在圖像上傳的時候, Big-man的這個項目沿用的是以前的代碼, 也就是每點擊一下去執行一下changeUpload()函數,而action的函數是在打包代碼里面,這里的Big-man的打包代碼是react-native。如下便是代碼:
import config from
"../config/config";
import ImagePicker from
'react-native-image-picker';
//第三方相機
import {Platform, Alert} from
'react-native'
import Log from
"../utils/LogUtil";
var UpLoadImage = {
//上傳圖片
upload:
function(message,callback,showTips,hidTips) {Log.log(
"####進入方法內:"+message.api);config.Authorization = message.Authorization;
let photoOptions = {
//底部彈出框選項
title:
'請選擇',
cancelButtonTitle:
'取消',
takePhotoButtonTitle:
'拍照',
chooseFromLibraryButtonTitle:
'選擇相冊',
quality:
0.3,
allowsEditing:
true,
noData:
false,
storageOptions: {
skipBackup:
true,
path:
'images'}};
// 選擇圖片ImagePicker.showImagePicker
(photoOptions,(response) => {if (response.didCancel){Log.log('User cancelled image picker');return;} else if (response.error) {Log.log('ImagePicker Error: ', response.error);return;} else if (response.customButton) {Log.log('User tapped custom button: ', response.customButton);return;}if (Platform.OS === 'ios') {const source = {uri: response.uri.replace('file://', ''), isStatic: true};this.uploadImageNetWork(source.uri,callback,message,showTips,hidTips);} else {const source = {uri: response.uri, isStatic: true};this.uploadImageNetWork(source.uri,callback,message,showTips,hidTips);}});},// 上傳圖片的網絡請求uploadImageNetWork : function(uri,callback,message,showTips,hidTips) {let split = uri.split('/');let p = split[split.length - 1];// 這里還沒有對 Uri 的非空判斷let formData = new FormData();let file = {uri, type: 'multipart/form-data', name: p}; // name截取Uri的最后字段formData.append("file",file); //這里的files就是后臺需要的keyshowTips();fetch(config.api+message.api,{method:'post',// mode: "cors",// 允許跨域訪問headers:{'Authorization':config.Authorization,'Content-Type':'multipart/form-data',},body:formData,}).then((response) => {if (response.ok){hidTips();Alert.alert('提示','上傳成功',[{text:'確定',onPress:()=>{}}]);callback();}else {hidTips();Alert.alert('提示','上傳失敗',[{text:'確定',onPress:()=>{}}]);}}).catch((e)=>{hidTips();Alert.alert('提示','系統錯誤',[{text:'確定',onPress:()=>{}}]);});}
}
export default UpLoadImage
- 更新圖片的邏輯很是復雜,Big-man會在接下來分析一下圖片的上傳過程。
進入圖片更新頁面之前:
- 在進入圖片更新之前, Big-man需要去插入一條空的數據, 類似于下面的代碼:
common:
function () {
let type =
3this.$http.get
(this.barAddUrl + type + '/').then((response) => {const ret = JSON.parse(response.data || "[]")if(ret && ret.code === 0) {this.id = ret.idthis.$router.replace('/postcommon/' + this.id)} else {Toast(ret.msg)}})
},
- 因為Big-man書寫的論壇里面還存在帖子的類型(活動帖和普通帖), 所以在這一步同時也需要上傳一個類型(type值),接下來看數據分析:
- barAddUrl的代碼分析:
$app->get(
'/bar/add/{type}/',
function($request, $response, $args) {global $g_tbwuserid,
$timestamp,
$g_city_id;
if (
$g_tbwuserid >
0) {
$bar = [];
$bar[
'type'] =
$args[
'type'];
$bar[
'istop'] =
1;
$bar[
'addtime'] =
$timestamp;
$bar[
'cityid'] =
$g_city_id;
$ret = template_add(
'cache_postbar', NO_CHECK_POWER,
$bar,
$request,
$response);}
else{
$ret[
'code'] =
1;
$ret[
'msg'] = COMMENT_LOGIN;return_result(
$request,
$response,
$ret);}
return $response;
});
- 后臺是采用PHP書寫的代碼, 這樣的操作是為了方便圖片的插入, Big-man這樣去想過這個數據的走勢,圖片需要插入,但是圖片處理需要與bar的主鍵值(也就是上圖中的id值)結合起來(不然怎么知道這張圖片是是那個帖子的圖片了),但是這個id值是DataBase自帶的自增屬性值(這里Big-man并沒有對每一個帖子設計一個主鍵值,因為MySQL中自帶的數據庫遞增值,很明顯可以處理完這類的需求),對于操作過的小伙伴們很明白這一點的,所以我在圖片上傳的頁面需要知道這個id值,如下圖:
- 上圖中的linkid也就是我這里的barid,與這個barid對應的也就是上述中的id值。
插入一條空數據:
- 很多的小伙伴可能會存在像Big-man這樣的疑問,為什么需要去插入一條空數據了?插入一條空數據有什么意義了?
- 占過座的伙伴們或者暗戀過別人的伙伴們就比較好理解這個內容,為什么了?因為這群伙伴很明白自己所占的東西雖然是空白的沒人使用,但是卻是實實在在屬于自己的物品。
- 插入圖片前插入一條空數據也是同樣的道理的,雖然那是一條空的數據, 但是卻是屬于這部分上傳圖片的空數據,當圖片上傳進來的時候,就回歸到這條空數據上的。當其他數據想要來強行插入的時候,不好意思,沒有那個通行證的同志不準進入。
圖片上傳刷新頁面:
- react-native中的機制,上傳圖片是app觸發的,所以需要查看app的代碼。代碼在上一部分已經給出,react-native老實說Big-man不是很熟悉, 曾經在一個大項目中接觸過幾個簡單的功能,曾經的Big-man還被一位經驗豐富的面試官打擊了,曾經的歷程就不再贅述。
react基本語法:
- Big-man先來解釋一下react的基本語法:
- ReactDOM.render(): 就這個問題曾經有一位伙伴問過Big-man這個問題, React中的render()如何理解, Big-man沉思了一下,就在這時這位伙伴又發過來說是不是渲染的含義,Big-man就回復了如果你在牛津英漢詞典或者有道翻譯上都是這個解釋,而且還會出現是計算機專業名稱解釋,但是如果是渲染的話,Big-man想不通,瀏覽器加載任何一個靜態的html文件,也會稱作瀏覽器渲染,但是為什么html文件里面沒有render這個詞匯,既然是說react中的render,Big-man就應該從react這群開發者”怪咖”出發,
Jackdan9 Thinking
總結
以上是生活随笔為你收集整理的Vue, App与我(十三)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。