「加薪DAY4」Vue.js项目经验总结-冒险岛2

「加薪DAY4」Vue.js项目经验总结-冒险岛2

项目介绍

《冒险岛2》岛民社区——一个APP内嵌HTML5页面的社区型专题。收到时他的PSD是这样。

作者:邵晓斌-腾讯重构工程师
@IMWeb前端社区,若未授权禁止转载

《冒险岛2》岛民社区设计稿

项目选型

其实当时拿到这个需求的时候,因为直接定义了其为APP内嵌社区,所以当时的判断是一个重交互型页面,应该为单页应用。原本我们的交互如果不是使用原生javascript的情况下,也使用了jquery等一些dom操作库,那么都到16年(这个前端技术爆发的一年?)所以我们是不是还要用继续用jquery来做呢?那么我们选用的方案是啥呢?答案当时是——MVVM~

那么说到MVVM库,我们首先想到的必然是当前比较火热的几个

  1. Angular
  2. React
  3. Vue

当然其实还有许多许多。

最终我选用了Vue,理由有几点:

  • 首先我之前使用过Angular,他俩很像。但是在API上来说Vue比Angular简单多了。而且Angular的断崖式更新的惨案也不绝于耳。想必用过Angular的各位一定记忆犹新。所以我果断还是放弃了Angular。
  • 其次我没有选用react,在vuejs.org上有vue和react的比较,其中有这样一句话:“React 团队雄心勃勃,计划让 React 成为通用平台的 UI 开发工具,而 Vue 专注于为 Web 提供实用的解决方案。” 所以相比重而复杂的react,我更偏向于小而美的Vue。
  • 最终我选择了既有中文文档,同时在github上star颇高,issues维护速度惊人,API和设计都相对简单的Vue.js。

Vue.js介绍

Vuejs.org上的一句宣传语:“数据驱动的组件,为现代化的 Web 界面而生”就可以总结Vue.js的全部了。

Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。Vue.js通过双向绑定来实现了View层和Model层的连接,
以数据驱动模型。

在使用 jQuery 手工操作 DOM 时,我们的代码常常是命令式的、重复的与易错的。而DOM在单页WEB应用中的问题有会有当我们重新渲染整个视图的成本是非常昂贵的,而且手动来更新DOM来保持视图和数据的同步很容易导致Bug。所以Vue.js 拥抱数据驱动的视图概念。一旦创建了绑定,DOM 将与数据保持同步。每当修改了数据,DOM 便相应地更新。这样我们应用中的逻辑就几乎都是直接修改数据了,不必与 DOM 更新搅在一起。这让我们的代码更容易撰写、理解与维护。

最后也是Vue很重要的一个概念就是组件系统。按照官网上的写法就是:“因为它提供了一种抽象,让我们可以用独立可复用的小组件来构建大型应用。如果我们考虑到这点,几乎任意类型的应用的界面都可以抽象为一个组件树:

所以Vue.js的核心思想就是数据驱动与组件化,他是一个专注在视图层的Web界面库~

Vue.js简单Demo

这里也是列举官方文档里的最简单的Demo,简单聊聊基础功能。

首先:

<div id="app">
     <p>{{message}}</p>
     <input type="text" v-model="message">
    <button v-on:click="reverseMessage">reverse message</button>
</div>

new Vue({
      el: '#appEvent',
      data: {
            message: '1'
          },
      methods: {
        reverseMessage: function() {
          this.message = this.message.split('').reverse().join('');
        }
      }
});

这里提供了Vue.js实例的构造方法,通过这简单的2行代码实现了图中的输入内容与视图层同步的功能。

我们所作的只是申明绑定了dom和相应的数据,就简单实现了双向绑定。然后通过事件的绑定操作数据这样视图层也同步更新。

我们再来看一下Vue.js的一些基础语法:

数据绑定语法

  • 插值
    • 文本 {{mag}} {{*msg}}
    • html {{{html}}}
    • html 属性 id=”item-{{id}}”
  • 绑定表达式
    • js表达式
    • 过滤器
  • 指令 v-if、v-show、v-else、v-for(遍历数组或对象) …

等等…

《岛2》社区中制作的一些简单功能(组件)

1.文本输入框

这个功能点上非常简单就是需要提供可输入的文字总量,并在超过时给出提示。所以这里利用Vue.js的双向绑定和样式绑定就可以轻松完成这个简单的功能。

<div class="edit-input-box">
<textarea name="sIntro" id="" class="mon-input" placeholder="分享你身边的趣事吧" v-model="message"></textarea>
<p class="font-num-box">
 <span v-bind:class="{'font-num-error':message.length>140}">{{message.length}}</span> /140)
</p>
<a href="javascript:;" class="edit-submit-btn">发送</a>
</div>

很简单的一步就完成了数据与视图的同步~

2.图片上传

图片上传的话功能点上会相对比较多总结整理的话

  1. 上传图片
  2. 新增小图浏览
  3. 点击提示可删除原上传图片
    <div class="upload-img-box cf">
        <template v-for="image in uploadList" track-by="$index">
            <div class="upload-img-item-warp" v-on:click="delLoadImage($index)">
                <div class="upload-img-item" style="background:url({{image}}) center center no-repeat"></div>
                <span class="upload-img-del-icon">×</span>
            </div>
        </template>
        <div class="upload-btn">
            <input type="file" class="inp-file" v-change="imageChange" name='file' id='J_file' />
        </div>
    </div>


    var upload = Vue.extend({
        template:"#uploadItem",
        data: { uploadList:[] }, 
        methods:{ 
            delLoadImage:function(index,e){....} 
            imageChange: function(event) {
                  var files = event.target.files || event.dataTransfer.files;
                  if (!files.length) return;
                  for (var i = 0; i < files.length; i++) {
                    this.createImage(files[i]);
                      }
                },
                   createImage: function(file) {
                      var image = new Image();
                      var reader = new FileReader();
                     var vm = this;
                      reader.onload = function(e) {
                           vm.images.push(e.target.result);
                        MXD2_UPLOAD.uploadImg('J_file');
                      };
                          reader.readAsDataURL(file);
                        }
                }
            })

上传图片依然只能使用type[file]按钮进行上传,在其结构上使用事件绑定指令v-change绑定方法,imageChage,通过执行Api FileReader来读取图片并创建,将图片数据保存在result数组中,通过v-for遍历此数组渲染出小图列表,当删除图片时,只需要通过splice切割数组即可以删除该图,同时渲染出当前列表,而且绑定在这个dom结构上的事件也会在删除的同时被销毁。

3.社区列表

其实社区的列表中的一条就可以拆分多个组件

  • 发布的文字信息
  • 列表图片
  • 时间/位置
  • 点赞
  • 评论列表
  • 功能操作工具条

‘具体社区列表结构如下:

//社区组件内部结构
<div class="monent-item">
    <div class="monents-user-face">
        <a href="#" class="face-img">
            <img v-if="data.sOpenId=='616d615a6d47466c6d5a706d62513d3d'" src="http://ossweb-img.qq.com/images/comm/blank.png" data-oxlazy="http://mxd2.qq.com/act/a20160809moments/manager.jpg"
                                        alt="管理员">
            <img v-else src="http://ossweb-img.qq.com/images/comm/blank.png" data-oxlazy="{{data.sUrl}}" alt="{{data.sNickName}}">
        </a>
    </div>
    <div class="monents-detail">
        <mon-info></mon-list>
        <div class="mon-info">
            <a href="" class="mon-info-name" v-bind:class="{'mon-info-name-admin':data.sOpenId=='616d615a6d47466c6d5a706d62513d3d'}">{{data.sNickName}}</a>
            <span v-if="data.sOpenId=='616d615a6d47466c6d5a706d62513d3d'" class="admin-icon-span">管理员</span>
            <div class="mon-type-box">
                <span v-if="data.Recommend" class="mon-hot-icon">推荐</span>
            </div>
        </div>
        <div class="mon-txt">
            <a href='#' class='a-topic'>#{{data.sTopic}}#</a>
            <span v-if="data.iExt1==1">分享了我的形象"{{data.sIntro}}"</span>
            <span v-else>{{data.sIntro}}</span>
        </div>
        <mon-imglist></mon-imglist>
        <mon-frome></mon-frome>
        <tool-box id='J_tool_{{data.hot}}_{{data.iContentId}}' :toolShow="toolShow" :owner="owner" :store="store" :data="data" :index="index"></tool-box>
        <div class="comment-box">
            <like-list></like-list>
            <moment-list></moment-list>
        </div>
    </div>
</div>

//实际调用时自定义结构
<monent-item v-for="(index,item) in searchmonent" :data="item" :owner="owner" :store="store" :index="index"></monent-item>

最终效果如下图:

大型项目

由于在一开始的规划中还未使用vue-cli来构建项目,利用webpack打包,最后来说一下我们如果是大型项目,显然使用模块化的构建方式更显科学。

构建单页应用。

由于Vue2.0已经发布默认使用2.0模板,如果要安装1.0模板 直接在vue init阶段 使用 webpack-simple#1.0 即可构建1.0模板

只有我们就可以使用单文件组件方式来模块化自己的项目,使用.vue文件,其中包括这个组件的全部内容——style,template和script。

然后官方也提供许多插件包括

  • axios(ajax)
  • vue-devtools(chrome开发者工具)
  • vue-router

等等。

最后的最后…

现阶段的前端正在快速道上飞奔,几乎每一天都会有新的知识新的名词出现,前几天还在说前端MVC这两年都在说MVVM,无论是Vue、Angular、React,包括React Native还有之前阿里无线开源Weex等。我们为了赶上这些只有在学习中不断在项目中实践。

岛2项目今后也会在各种方面不断尝试Vue.js来实现各种功能,当然无论是直接用script单文件引入,还是对于一些大型项目使用Webpack构建的SPA。最后还是要赞一句所有这都归功于官方健全的文档,优质的社区资源。



腾讯课堂IMWeb十天前端加薪训练营链接

若你阅读该文中有什么疑问,欢迎在下方评论区留言,我们会选择部分问题解答
编辑于 2017-04-18 13:14