Vue, App与我(十三)

Vue, App与我(十三)

前言:

  • Big-man需要开发一个论坛模块, 论坛模块的话,简而言之, 就是一个发帖和回帖的模块。但是Big-man的这个论坛模块还是比较复杂的。在接下来的实现中Big-man会进一步地去进行分析。所以Big-man怀着好奇的心态进入了移动端的论坛模块。

首页:

post

  • 从这个首页的设计图上就可以得出, 需求是多么地繁杂,特别是涉及到图片上传这一块,原来的头像更换代码, 也是相当于图片上传。代码如下:
<template>
  <div>
    <div class="navTop">
      <i class="iconfont back" onclick="javascript:history.go(-1)">&#xe609;</i>
      <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是定义隐藏的字段,这里这样写主要是想要通过样式实现如下的效果:
    plus
  • 查看如下的样式修饰代码:
<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.value
      this.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 = true
       this.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就是后台需要的key
        showTips();
        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 = 3
    this.$http.get(this.barAddUrl + type + '/').then((response) => {
        const ret = JSON.parse(response.data || "[]")
        if(ret && ret.code === 0) {
            this.id = ret.id
            this.$router.replace('/postcommon/' + this.id)
        } else {
            Toast(ret.msg)
        }
    })
},
  • 因为Big-man书写的论坛里面还存在帖子的类型(活动帖普通帖), 所以在这一步同时也需要上传一个类型(type),接下来看数据分析:
    DB
  • 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值,如下图:
    bar_pic
  • 上图中的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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值