vue2.0聊天室vue-chatRoom|仿微信界面vue+vuex+vueRouter

Vue2.0+Vuex+VueRouter仿微信界面聊天室|仿微信聊天窗口|仿微信群聊

基于vue2.0+vuex+webpack2.0+es6+wcPop等技术开发的仿微信聊天室vue-weChatRoom实战项目,实现了下拉刷新聊天消息,发送信息、表情(gif),预览大图、视频,打赏、红包等功能。

h5仿微信聊天室:https://blog.csdn.net/yanxinyun1990/article/details/84890686

  

◆ vue-router页面地址路由:

/*
 *  页面地址路由js
 */ 
import Vue from 'vue'
import _router from 'vue-router'
import store from '../vuex'

Vue.use(_router) //应用路由

const router = new _router({
    routes: [
        // 登录、注册
        {
            path: '/login',
            component: resolve => require(['../views/auth/login'], resolve),
        },
        {
            path: '/register',
            component: resolve => require(['../views/auth/register'], resolve),
        },

        // 首页、通讯录、我
        {
            path: '/',
            component: resolve => require(['../views/index'], resolve),
            meta: { showHeader: true, showTabBar: true, requireAuth: true }
        },
        {
            path: '/contact',
            component: resolve => require(['../views/contact'], resolve),
            meta: { showHeader: true, showTabBar: true, requireAuth: true },
        },
        {
            path: '/contact/uinfo',
            component: resolve => require(['../views/contact/uinfo'], resolve),
        },
        {
            path: '/ucenter',
            component: resolve => require(['../views/ucenter'], resolve),
            meta: { showHeader: true, showTabBar: true, requireAuth: true }
        },
        // 聊天页面
        {
            path: '/chat/group-chat',
            component: resolve => require(['../views/chat/group-chat'], resolve),
            meta: { requireAuth: true }
        },
        {
            path: '/chat/single-chat',
            component: resolve => require(['../views/chat/single-chat'], resolve),
            meta: { requireAuth: true }
        },
        {
            path: '/chat/group-info',
            component: resolve => require(['../views/chat/group-info'], resolve),
            meta: { requireAuth: true }
        }

        // ...
    ]
})

// 注册全局钩子拦截登录状态
const that = this
router.beforeEach((to, from, next) => {
    const token = store.state.token
    // 判断该路由地址是否需要登录权限
    if(to.meta.requireAuth){
        // 通过vuex state获取当前token是否存在
        if(token){
            next()
        }else{
            // console.log('还未登录授权!')
            next()
            wcPop({
                content: '还未登录授权!', style: 'background:#e03b30;color:#fff;', time: 2,
                end: function(){
                    next({ path: '/login' })
                }
            });
        }
    }else{
        next()
    }
})

export default router

◆ vuex状态管理器

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        user: window.sessionStorage.getItem('user'),
        token: window.sessionStorage.getItem('token')
    },
    mutations: {
        // 将token存储到sessionStorage
        SET_TOKEN (state, data){
            state.token = data;
            window.sessionStorage.setItem('token', data);
        },
        // 获取用户名
        SET_USER (state, data){
            state.user = data;
            window.sessionStorage.setItem('user', data);
        },
        // 退出
        LOGOUT (state){
            state.user = null;
            state.token = null;
            window.sessionStorage.removeItem('user');
            window.sessionStorage.removeItem('token');
        }
    },
    getters:{}
})
// >>> 【表情、动图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 = new Swiper('#' + _tmpl, {
		// loop: true,
		// autoplay: true,
		// 分页器
		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);
			})
		}
	});
});


// >>> 【编辑器+表情处理模块】------------------------------------------
// ...处理编辑器信息
function surrounds() {
	setTimeout(function () { //chrome
		var sel = window.getSelection();
		var anchorNode = sel.anchorNode;
		if (!anchorNode) return;
		if (sel.anchorNode === $(".J__wcEditor")[0] ||
			(sel.anchorNode.nodeType === 3 && sel.anchorNode.parentNode === $(".J__wcEditor")[0])) {

			var range = sel.getRangeAt(0);
			var p = document.createElement("p");
			range.surroundContents(p);
			range.selectNodeContents(p);
			range.insertNode(document.createElement("br")); //chrome
			sel.collapse(p, 0);

			(function clearBr() {
				var elems = [].slice.call($(".J__wcEditor")[0].children);
				for (var i = 0, len = elems.length; i < len; i++) {
					var el = elems[i];
					if (el.tagName.toLowerCase() == "br") {
						$(".J__wcEditor")[0].removeChild(el);
					}
				}
				elems.length = 0;
			})();
		}
	}, 10);
}

// 定义最后光标位置
var _lastRange = null, _sel = window.getSelection && window.getSelection();
var _rng = {
	getRange: function () {
		if (_sel && _sel.rangeCount > 0) {
			return _sel.getRangeAt(0);
		}
	},
	addRange: function () {
		if (_lastRange) {
			_sel.removeAllRanges();
			_sel.addRange(_lastRange);
		}
	}
}

// 格式化编辑器包含标签
$("body").on("click", ".J__wcEditor", function(){
	$(".wc__choose-panel").hide();
});
$("body").on("focus", ".J__wcEditor", function(){
	surrounds();
});
$("body").on("input", ".J__wcEditor", function(){
	surrounds();
});

// 点击表情
$("body").on("click", "#J__swiperEmotion .face-list span img", function () {
	var that = $(this), range;

	if (that.hasClass("face")) { //小表情
		var img = that[0].cloneNode(true);
		if (!$(".J__wcEditor")[0].childNodes.length) {
			$(".J__wcEditor")[0].focus();
		}
		$(".J__wcEditor")[0].blur(); //输入表情时禁止输入法

		setTimeout(function () {
			if (document.selection && document.selection.createRange) {
				document.selection.createRange().pasteHTML(img);
			} else if (window.getSelection && window.getSelection().getRangeAt) {
				range = _rng.getRange();
				range.insertNode(img);
				range.collapse(false);

				_lastRange = range; //记录当前光标位置 (否则光标会跑到表情前面)
				_rng.addRange();
			}
		}, 10);
	} else if (that.hasClass("del")) { //删除
		// _editor.focus();
		$(".J__wcEditor")[0].blur(); //输入表情时禁止输入法

		setTimeout(function () {
			range = _rng.getRange();
			range.collapse(false);
			document.execCommand("delete");

			_lastRange = range;
			_rng.addRange();
		}, 10);
	} else if (that.hasClass("lg-face")) { //大表情
		var _img = that.parent().html();
		var _tpl = [
			'<li class="me">\
				<div class="content">\
					<p class="author">王梅(Fine)</p>\
					<div class="msg lgface">'+ _img + '</div>\
				</div>\
				<a class="avatar" href="/contact/uinfo"><img src="src/assets/img/uimg/u__chat-img11.jpg" /></a>\
			</li>'
		].join("");
		$("#J__chatMsgList").append(_tpl);

		wchat_ToBottom();
	}
});

 

  • 8
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,以下是一个简单的微信聊天页面的 Vue 实现,包括消息列表、输入框和发送按钮。这个例子中的数据是硬编码的,可以根据实际需求进行修改。 ```html <template> <div class="chat-container"> <div class="message-list"> <div class="message" v-for="(message, index) in messages" :key="index"> <div class="message-content">{{ message.content }}</div> <div class="message-time">{{ message.time }}</div> </div> </div> <div class="input-container"> <input type="text" v-model="newMessage" class="message-input" /> <button @click="sendMessage" class="send-button">发送</button> </div> </div> </template> <script> export default { data() { return { messages: [ { content: '你好!', time: '2023-02-27 10:00:00' }, { content: '最近怎么样?', time: '2023-02-27 10:05:00' }, { content: '很好,谢谢。你呢?', time: '2023-02-27 10:10:00' }, { content: '也很好,谢谢。', time: '2023-02-27 10:15:00' }, ], newMessage: '', }; }, methods: { sendMessage() { const now = new Date(); const time = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`; this.messages.push({ content: this.newMessage, time }); this.newMessage = ''; }, }, }; </script> <style> .chat-container { display: flex; flex-direction: column; height: 100%; } .message-list { flex: 1; overflow-y: scroll; } .message { padding: 10px; margin-bottom: 10px; background-color: #f0f0f0; border-radius: 5px; } .message-content { font-size: 16px; } .message-time { font-size: 12px; color: #666; margin-top: 5px; text-align: right; } .input-container { display: flex; align-items: center; margin-top: 10px; } .message-input { flex: 1; padding: 10px; border-radius: 5px; border: 1px solid #ccc; font-size: 16px; margin-right: 10px; } .send-button { padding: 10px; border-radius: 5px; background-color: #1aad19; color: #fff; font-size: 16px; border: none; cursor: pointer; } </style> ``` 在这个例子中,我们使用了 Vue 的模板语法来定义页面结构,并在 `<script>` 标签中定义了相应的数据和方法。 在 `data` 函数中,我们定义了 `messages` 数组,用于存储所有的聊天消息,和 `newMessage` 字符串,用于存储用户输入的新消息。`sendMessage` 方法用于将用户

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoyan_2018

你的鼓励将是我持续作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值