vue仿微信网页版|vue+web端聊天室|仿微信客户端vue版
一、项目介绍
基于 Vue2.5.6+Vuex+vue-cli+vue-router+vue-gemini-scrollbar+swiper+elementUI 等技术混合架构开发的仿微信 web 端聊天室——vueWebChat,实现了发送消息、表情 (动图),图片、视频预览,右键菜单、截屏、截图可直接粘贴至文本框进行发送。
二、技术框架
- MVVM 框架:Vue2.5.6
- 状态管理:Vuex
- 页面路由:Vue-router
- iconfont 图标:阿里巴巴字体图标库
- 自定义滚动条:vue-gemini-scrollbar
- 弹窗组件:element-ui(饿了么前端 UI 库)
- 环境配置:node.js + cnpm + webpack
- 高德地图:vue-amap
- 图片预览:vue-photo-preview
◆ 点击右上角最大化按钮,可以进行全屏切换
◆ 引入公共及全局组件配置 components.js
/* 引入公共及全局组件配置 */// 引入侧边栏及联系人
import winBar from './components/winbar'
import sideBar from './components/sidebar'
import recordList from './components/recordList'
import contactList from './components/contact'// 引入 jquery
import $ from 'jquery'// 引入 wcPop 弹窗插件
import wcPop from './assets/js/wcPop/wcPop'
import './assets/js/wcPop/skin/wcPop.css'// 引入饿了么 pc 端 UI 库
import elementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'// 引入图片预览插件
import photoPreview from 'vue-photo-preview'
import 'vue-photo-preview/dist/skin.css'// 引入自定义滚动条插件
import geminiScrollbar from 'vue-gemini-scrollbar'// 引入加载更多插件
import infiniteLoading from 'vue-infinite-scroll'// 引入高德地图
import vueAMap from 'vue-amap'const install = Vue => {
// 注册组件
Vue.component('win-bar', winBar)
Vue.component('side-bar', sideBar)
Vue.component('record-list', recordList)
Vue.component('contact-list', contactList)</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 应用实例</span>
Vue.use(elementUI)
Vue.use(photoPreview, {
loop: false,
fullscreenEl: true, //是否全屏
arrowEl: true, //左右按钮
});
Vue.use(geminiScrollbar)
Vue.use(infiniteLoading)
Vue.use(vueAMap)
vueAMap.initAMapApiLoader({
key: "e1dedc6bdd765d46693986ff7ff969f4",
plugin: [
"AMap.Autocomplete", //输入提示插件
"AMap.PlaceSearch", //POI 搜索插件
"AMap.Scale", //右下角缩略图插件 比例尺
"AMap.OverView", //地图鹰眼插件
"AMap.ToolBar", //地图工具条
"AMap.MapType", //类别切换控件,实现默认图层与卫星图、实施交通图层之间切换的控制
"AMap.PolyEditor", //编辑 折线多,边形
"AMap.CircleEditor", //圆形编辑器插件
"AMap.Geolocation" //定位控件,用来获取和展示用户主机所在的经纬度位置
],
uiVersion: "1.0"
});}
export default install
◆ 主页面模板
<template> <div id="app"> <div class="vChat-wrapper flexbox flex-alignc"> <div class="vChat-panel" style="background-image: url(src/assets/img/placeholder/vchat__panel-bg01.jpg);"> <div class="vChat-inner flexbox"> <!-- // 顶部按钮 (最大、最小、关闭) --> <win-bar></win-bar><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> //侧边栏 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">side-bar</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">side-bar</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">keep-alive</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">router-view </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="flex1 flexbox"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">router-view</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">keep-alive</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">></span>
</div>
</template><script>
export default {
name: 'app',
data () {
return {}
},
methods: {},
}
</script><style>
/ 引入公共样式 /
@import './assets/fonts/iconfont.css';
@import './assets/css/reset.css';
@import './assets/css/layout.css';</style>
◆ vue 文本框实现截图粘贴发送图片:
// 【截图粘贴图片】 document.getElementById('J__wcEditor').addEventListener('paste',function(e){ var cbd = e.clipboardData; var ua = window.navigator.userAgent; // 没有数据 if (!(e.clipboardData && e.clipboardData.items)) { return; } // Mac 平台下 Chrome49 版本以下 复制 Finder 中的文件的 Bug Hack 掉 if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" && cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" && ua.match(/Macintosh/i)&& Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49){ return; } for(var i = 0; i < cbd.items.length; i++){ var item = cbd.items[i]; console.log(item); console.log(item.kind); if(item.kind == "file"){ var blob = item.getAsFile(); if(blob.size === 0){ return; } // 插入图片记录 var reader = new FileReader(); reader.readAsDataURL(blob); reader.onload = function(){ var _img = this.result;</span><span style="color: rgba(0, 0, 255, 1)">var</span> _tpl =<span style="color: rgba(0, 0, 0, 1)"> [ </span>'<span style="color: rgba(0, 0, 0, 1)"><li class="me">\ <div class="content">\ <p class="author">王梅(Fine)</p>\ <div class="msg picture"><img class="img__pic" src="</span>'+ _img + '<span style="color: rgba(0, 0, 0, 1)">" preview="1" /></div>\ </div>\ <a class="avatar" href="/contact/uinfo"><img src="src/assets/img/uimg/u__chat-img11.jpg" /></a>\ </li></span>'<span style="color: rgba(0, 0, 0, 1)"> ].join(</span>""<span style="color: rgba(0, 0, 0, 1)">); $(</span>"#J__chatMsgList"<span style="color: rgba(0, 0, 0, 1)">).append(_tpl); setTimeout(() </span>=><span style="color: rgba(0, 0, 0, 1)"> { $(</span>"#J__geminiScrollbar .gm-scroll-view").animate({ scrollTop: $("#J__chatMsgList").height() }, 0<span style="color: rgba(0, 0, 0, 1)">); $(</span>".fixGeminiscrollHeight"<span style="color: rgba(0, 0, 0, 1)">).show(); setTimeout(() </span>=> { $(".fixGeminiscrollHeight").hide();}, 300<span style="color: rgba(0, 0, 0, 1)">); }, </span>17<span style="color: rgba(0, 0, 0, 1)">); } } }
});
◆ 表情处理及视频预览:
// >>> 【表情、动图 swiper 切换模块】-------------------------- var emotionSwiper; function setEmotionSwiper(tmpl) { var _tmpl = tmpl ? tmpl : $("#J__emotionFootTab ul li.cur").attr("tmpl"); $("#J__swiperEmotion .swiper-container").attr("id", _tmpl); $("#J__swiperEmotion .swiper-wrapper").html($("." + _tmpl).html());emotionSwiper </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Swiper('#' +<span style="color: rgba(0, 0, 0, 1)"> _tmpl, { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> loop: true,</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> autoplay: true,</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 分页器</span>
pagination: {
el: '.pagination-emotion', clickable: true,
},
});
}
// 表情模板切换
$("body").on("click", "#J__emotionFootTab ul li.swiperTmpl", function () {
// 先销毁 swiper
emotionSwiper && emotionSwiper.destroy(true, true);
var _tmpl = $(this).attr("tmpl");
$(this).addClass("cur").siblings().removeClass("cur");setEmotionSwiper(_tmpl);
});
// >>> 【视频预览模块】--------------------------
$("body").on("click", "#J__chatMsgList li .video", function () {
var _src = $(this).find("img").attr("videoUrl"), _video;
var videoIdx = wcPop({
id: 'wc__previewVideo',
skin: 'fullscreen',
// content: '<video id="J__videoPreview"width="100%"height="100%"controls="controls"x5-video-player-type="h5"x5-video-player-fullscreen="true"webkit-playsinline preload="auto"></video>',
content: '<video id="J__videoPreview"width="100%"height="100%"controls="controls"preload="auto"></video>',
shade: false,
xclose: true,
style: 'background: #000;padding-top:48px;',
anim: 'scaleIn',
show: function(){
_video = document.getElementById("J__videoPreview");
_video.src = _src;
if (_video.paused) {
_video.play();
} else {
_video.pause();
}
// 播放结束
_video.addEventListener("ended", function(){
_video.currentTime = 0;
});
// 退出全屏
_video.addEventListener("x5videoexitfullscreen", function(){
wcPop.close(videoIdx);
})
}
});
});