创新实训周报五(第十一周)聊天js部分,主要使用vuex管理

最开始写时也只是打算使用原本的方法,各个页面与后端直接交互数据,后来发现很麻烦,而且在先不写后端的情况下,我们每周汇报时要展示成果,也必须有数据,所以最终就选择了vuex管理前端数据。上一周写的那些界面的js部分都是用来与vuex收发数据的,具体代码在第十周的博客,都是一些流程性的固定的东西。接下来展示存储在store.js里的东西

项目结构

src/
├── assets/                      # 资源文件夹
│   └── chat/                    # 聊天相关资源
│       └── images/              # 图片资源
├── components/                  # 组件文件夹
│   └── Chat.vue                 # 聊天组件
├── router.js                    # 路由配置文件
├── store.js                     # Vuex 状态管理文件
├── WebSocketService.js          # WebSocket 服务
└── EventBus.js                  # 事件总线

vuex简介

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它通过集中式存储管理应用的所有组件的状态,并以规则保证状态以一种可预测的方式发生变化。Vuex 主要用于中大型单页面应用(SPA),可以有效管理共享状态,解决跨组件通信复杂的问题。

核心概念

  1. State(状态)

    • Vuex 使用单一状态树,即一个对象包含了全部的应用层级状态。这个状态树作为唯一的数据源,非常便于追踪和调试。
    • 组件可以通过 this.$store.state 访问状态。
  2. Getters(获取器)

    • Getters 类似于组件的计算属性,允许从 state 派生出一些状态。它们可以缓存并在依赖的状态发生变化时重新计算。
    • 组件可以通过 this.$store.getters 访问 getters。
  3. Mutations(突变)

    • Mutations 是同步函数,用于修改 Vuex 的 state。每个 mutation 都有一个字符串的事件类型(type)和一个回调函数(handler)。
    • 组件可以通过 this.$store.commit('mutationType', payload) 触发 mutations。
  4. Actions(动作)

    • Actions 类似于 mutations,不同在于:
      1. Actions 提交的是 mutations,而不是直接变更状态。
      2. Actions 可以包含任意异步操作。
    • 组件可以通过 this.$store.dispatch('actionType', payload) 触发 actions。
  5. Modules(模块)

    • 当应用变得非常复杂时,可以将 Vuex 的 store 分割成模块(module)。每个模块拥有自己的 state、mutations、actions 和 getters。

我的代码

state

const store = new Vuex.Store({
    state: {
        // 输入的搜索值
        searchText: '',

        // 当前登录用户
        user: {
            name: '',
            img: '',
        },
        // 对话好友列表

        chatlist: [

        ],
        // 好友列表
        friendlist: [
            {
                id: 0,
                wxid: "", //微信号
                initial: '新的朋友', //姓名首字母
                img: require('@/assets/chat/images/1.jpg'), //头像
                signature: "", //个性签名
                nickname: "新的朋友",  //昵称
                sex: 0,   //性别 1为男,0为女
                remark: "新的朋友",  //备注
                area: "",  //地区
            },
            {
                id: 1,
                wxid: "AmorAres-", //微信号
                initial: 'A', //姓名首字母
                img: require('@/assets/chat/images/1.jpg'), //头像
                signature: "每天我都很快乐", //个性签名
                nickname: "Amor",  //昵称
                sex: 0,   //性别 1为男,0为女
                remark: "Amor",  //备注
                area: "浙江 宁波",  //地区
            },
            {
                id: 2,
                wxid: "fly",
                initial: 'B',
                img: require('@/assets/chat/images/1.jpg'),
                signature: "你不知道的js",
                nickname: "fly",
                sex: 1,
                remark: "大飞",
                area: "奥地利 布尔根兰",
            }

        ],

        //医生列表
        doctor: [

            {
                id: 9,
                wxid: "Seto_L",
                img: require('@/assets/chat/images/4.jpg'),
                signature: "自强不息",
                nickname: "王医生",
                sex: 1,
                remark: "王",
                area: "北京",
            },
            {
                id: 10,
                wxid: "hj960503",
                img: require('@/assets/chat/images/3.jpg'),
                signature: "哈哈哈",
                nickname: "李医生",
                sex: 1,
                remark: "YYY",
                area: "大连",
            }

        ],
        //emoji表情
        emojis: [
            { file: '100.gif', code: '/::)', title: '微笑', reg: /\/::\)/g },
            { file: '101.gif', code: '/::~', title: '伤心', reg: /\/::~/g },
            { file: '102.gif', code: '/::B', title: '美女', reg: /\/::B/g },
            { file: '103.gif', code: '/::|', title: '发呆', reg: /\/::\|/g },
            { file: '104.gif', code: '/:8-)', title: '墨镜', reg: /\/:8-\)/g },
            { file: '105.gif', code: '/::<', title: '哭', reg: /\/::</g },
            { file: '106.gif', code: '/::$', title: '羞', reg: /\/::\$/g },
            { file: '107.gif', code: '/::X', title: '哑', reg: /\/::X/g },
            { file: '108.gif', code: '/::Z', title: '睡', reg: /\/::Z/g },
            { file: '109.gif', code: '/::\'(', title: '哭', reg: /\/::'\(/g },
            { file: '110.gif', code: '/::-|', title: '囧', reg: /\/::-\|/g },
            { file: '111.gif', code: '/::@', title: '怒', reg: /\/::@/g },
            { file: '112.gif', code: '/::P', title: '调皮', reg: /\/::P/g },
            { file: '113.gif', code: '/::D', title: '笑', reg: /\/::D/g },
            { file: '114.gif', code: '/::O', title: '惊讶', reg: /\/::O/g },
            { file: '115.gif', code: '/::(', title: '难过', reg: /\/::\(/g },
            { file: '116.gif', code: '/::+', title: '酷', reg: /\/::\+/g },
            { file: '117.gif', code: '/:--b', title: '汗', reg: /\/:--b/g },
            { file: '118.gif', code: '/::Q', title: '抓狂', reg: /\/::Q/g },
            { file: '119.gif', code: '/::T', title: '吐', reg: /\/::T/g },
            { file: '120.gif', code: '/:,@P', title: '笑', reg: /\/:,@P/g },
            { file: '121.gif', code: '/:,@-D', title: '快乐', reg: /\/:,@-D/g },
            { file: '122.gif', code: '/::d', title: '奇', reg: /\/::d/g },
            { file: '123.gif', code: '/:,@o', title: '傲', reg: /\/:,@o/g },
            { file: '124.gif', code: '/::g', title: '饿', reg: /\/::g/g },
            { file: '125.gif', code: '/:|-)', title: '累', reg: /\/:\|-\)/g },
            { file: '126.gif', code: '/::!', title: '吓', reg: /\/::!/g },
            { file: '127.gif', code: '/::L', title: '汗', reg: /\/::L/g },
            { file: '128.gif', code: '/::>', title: '高兴', reg: /\/::>/g },
            { file: '129.gif', code: '/::,@', title: '闲', reg: /\/::,@/g },
            { file: '130.gif', code: '/:,@f', title: '努力', reg: /\/:,@f/g },
            { file: '131.gif', code: '/::-S', title: '骂', reg: /\/::-S/g },
            { file: '133.gif', code: '/:,@x', title: '秘密', reg: /\/:,@x/g },
            { file: '134.gif', code: '/:,@@', title: '乱', reg: /\/:,@@/g },
            { file: '135.gif', code: '/::8', title: '疯', reg: /\/::8/g },
            { file: '136.gif', code: '/:,@!', title: '哀', reg: /\/:,@!/g },
            { file: '137.gif', code: '/:!!!', title: '鬼', reg: /\/:!!!/g },
            { file: '138.gif', code: '/:xx', title: '打击', reg: /\/:xx/g },
            { file: '139.gif', code: '/:bye', title: 'bye', reg: /\/:bye/g },
            { file: '142.gif', code: '/:handclap', title: '鼓掌', reg: /\/:handclap/g },
            { file: '145.gif', code: '/:<@', title: '什么', reg: /\/:<@/g },
            { file: '147.gif', code: '/::-O', title: '累', reg: /\/::-O/g },
            { file: '153.gif', code: '/:@x', title: '吓', reg: /\/:@x/g },
            { file: '155.gif', code: '/:pd', title: '刀', reg: /\/:pd/g },
            { file: '156.gif', code: '/:<W>', title: '水果', reg: /\/:<W>/g },
            { file: '157.gif', code: '/:beer', title: '酒', reg: /\/:beer/g },
            { file: '158.gif', code: '/:basketb', title: '篮球', reg: /\/:basketb/g },
            { file: '159.gif', code: '/:oo', title: '乒乓', reg: /\/:oo/g },
            { file: '195.gif', code: '/:circle', title: '跳舞', reg: /\/:circle/g },
            { file: '160.gif', code: '/:coffee', title: '咖啡', reg: /\/:coffee/g }
        ],
        icon: [
            "😀",
            "😃",
            "😄",
            "😁",
            "😆",
            "😅",
            "🤣",
            "😂",
            "🙂",
            "🙃",
            "😉",
            "😊",
            "😇",
            "😍",
            "🤩",
            "😘",
            "😗",
            "😚",
            "😙",
            "😋",
            "😛",
            "😜",
            "🤪",
            "😝",
            "🤑",
            "🤗",
            "🤭",
            "🤫",
            "🤔",
            "🤐",
            "🤨",
            "😐",
            "😑",
            "😶",
            "😏",
            "😒",
            "🙄",
            "😬",
            "🤥",
            "😌",
            "😔",
            "😪",
            "🤤",
            "😴",
            "😷",
            "🤒",
            "🤕",
            "🤢",
            "🤮",
            "🤧",
            "😵",
            "🤯",
            "🤠",
            "😎",
            "🤓",
            "🧐",
            "😕",
            "😟",
            "🙁",
            "😮",
            "😯",
            "😲",
            "😳",
            "😦",
            "😧",
            "😨",
            "😰",
            "😥",
            "😢",
            "😭",
            "😱",
            "😖",
            "😣",
            "😞",
            "😓",
            "😩",
            "😫",
            "😤",
            "😡",
            "😠",
            "🤬",
            "😈",
            "👿",
            "💀",
            "💩",
            "🤡",
            "👹",
            "👺",
            "👻",
            "👽",
            "👾",
            "🤖",
            "😺",
            "😸",
            "😹",
            "😻",
            "😼",
            "😽",
            "🙀",
            "😿",
            "😾",
            "💋",
            "👋",
            "🤚",
            "🖐",
            "✋",
            "🖖",
            "👌",
            "🤞",
            "🤟",
            "🤘",
            "🤙",
            "👈",
            "👉",
            "👆",
            "🖕",
            "👇",
            "👍",
            "👎",
            "✊",
            "👊",
            "🤛",
            "🤜",
            "👏",
            "🙌",
            "👐",
            "🤲",
            "🤝",
            "🙏",
            "💅",
            "🤳",
            "💪",
            "👂",
            "👃",
            "🧠",
            "👀",
            "👁",
            "👅",
            "👄",
            "👶",
            "🧒",
            "👦",
            "👧",
            "🧑",
            "👱",
            "👨",
            "🧔",
            "👱‍",
            "👨‍",
            "👨‍",
            "👨‍",
            "👨‍",
            "👩",
            "👱‍",
            "👩‍",
            "👩‍",
            "👩‍",
            "👩‍",
            "🧓",
            "👴",
            "👵",
            "🙍",
            "🙍‍",
            "🙍‍",
            "🙎",
            "🙎‍",
            "🙎‍",
            "🙅",
            "🙅‍",
            "🙅‍",
            "🙆",
            "🙆‍",
            "🙆‍",
            "💁",
            "💁‍",
            "💁‍",
            "🙋",
            "🙋‍",
            "🙋‍",
            "🙇",
            "🙇‍",
            "🙇‍",
            "🤦",
            "🤦‍",
            "🤦‍",
            "🤷",
            "🤷‍",
            "🤷‍",
            "👨‍⚕️",
            "👩‍⚕️",
            "👨‍🎓",
            "👩‍🎓",
            "👨‍🏫",
            "👩‍🏫",
            "👨‍⚖️",
            "👩‍⚖️",
            "👨‍🌾",
            "👩‍🌾",
            "👨‍🍳",
            "👩‍🍳",
            "👨‍🔧",
            "👩‍🔧",
            "👨‍🏭",
            "👩‍🏭",
            "👨‍💼",
            "👩‍💼",
            "👨‍🔬",
            "👩‍🔬",
            "👨‍💻",
            "👩‍💻",
            "👨‍🎤",
            "👩‍🎤",
            "👨‍🎨",
            "👩‍🎨",
            "👨‍✈️",
            "👩‍✈️",
            "👨‍🚀",
            "👩‍🚀",
            "👨‍🚒",
            "👩‍🚒",
            "👮",
            "👮‍♂️",
            "👮‍♀️",
            "🕵",
            "🕵️‍♂️",
            "🕵️‍♀️",
            "💂",
            "💂‍",
            "💂‍",
            "👷",
            "👷‍",
            "👷‍",
            "🤴",
            "👸",
            "👳",
            "👳‍",
            "👳‍",
            "👲",
            "🧕",
            "🤵",
            "👰",
            "🤰",
            "🤱",
            "👼",
            "🎅",
            "🤶",
            "🧙",
            "🧙‍",
            "🧙‍",
            "🧚",
            "🧚‍",
            "🧚‍",
            "🧛",
            "🧛‍",
            "🧛‍",
            "🧜",
            "🧜‍",
            "🧜‍",
            "🧝",
            "🧝‍",
            "🧝‍",
            "🧞",
            "🧞‍",
            "🧞‍",
            "🧟",
            "🧟‍",
            "🧟‍",
            "💆",
            "💆‍",
            "💆‍",
            "💇",
            "💇‍",
            "💇‍",
            "🚶",
            "🚶‍",
            "🚶‍",
            "🏃",
            "🏃‍",
            "🏃‍",
            "💃",
            "🕺",
            "🕴",
            "👯",
            "👯‍",
            "👯‍",
            "🧖",
            "🧖‍",
            "🧖‍",
            "🧘",
            "👭",
            "👫",
            "👬",
            "💏",
            "👨‍",
            "👩‍",
            "💑",
            "👨‍",
            "👩‍",
            "👪",
            "👨‍👩‍👦",
            "👨‍👩‍👧",
            "👨‍👩‍👧‍👦",
            "👨‍👩‍👦‍👦",
            "👨‍👩‍👧‍👧",
            "👨‍👨‍👦",
            "👨‍👨‍👧",
            "👨‍👨‍👧‍👦",
            "👨‍👨‍👦‍👦",
            "👨‍👨‍👧‍👧",
            "👩‍👩‍👦",
            "👩‍👩‍👧",
            "👩‍👩‍👧‍👦",
            "👩‍👩‍👦‍👦",
            "👩‍👩‍👧‍👧",
            "👨‍👦",
            "👨‍👦‍👦",
            "👨‍👧",
            "👨‍👧‍👦",
            "👨‍👧‍👧",
            "👩‍👦",
            "👩‍👦‍👦",
            "👩‍👧",
            "👩‍👧‍👦",
            "👩‍👧‍👧",
            "🗣",
            "👤",
            "👥",
            "👣",
            "🌂",
            "☂",
            "👓",
            "🕶",
            "👔",
            "👕",
            "👖",
            "🧣",
            "🧤",
            "🧥",
            "🧦",
            "👗",
            "👘",
            "👙",
            "👚",
            "👛",
            "👜",
            "👝",
            "🎒",
            "👞",
            "👟",
            "👠",
            "👡",
            "👢",
            "👑",
            "👒",
            "🎩",
            "🎓",
            "🧢",
            "⛑",
            "💄",
            "💍",
            "💼"
        ],
        // 得知当前选择的是哪个对话
        selectId: 1,
        // 得知当前选择的是哪个好友
        selectFriendId: 0,
        //当前选择的是哪个医生
        selectDoctorId: 0
    },

主要是朋友列表,聊天列表,表情,还有几个变量负责控制等等

mutation

 addMessagesToList(state, mes) {
            console.log(state.user.uname)
            // 遍历后端返回的消息列表,并添加到chatlist中  
            mes.forEach(message => {
                if (message.fid !== state.user.id) {
                    state.chatlist.push({
                        id: message.fid, // 假设后端有fid字段  
                        user: {
                            name: message.name,
                            img: message.imgUrl, // 假设后端有imgUrl字段
                        },
                        messages: message.messages.map(msg => ({
                            content: msg.content,
                            date: new Date(msg.time), // 假设后端返回的是时间字符串,转换为Date对象  
                            self: msg.self
                        }))

                    });
                }
            });

        },
        setUsername(state) {
            const user = JSON.parse(sessionStorage.getItem('user'));
            state.user.uname = user.uname;
            console.log(state.user.uname)
        },

        // 设置好友列表
        addMessage(state, mes) {
            state.chatlist.push(mes);
        },
        addChatMessage(state, msg) {
            let result = state.chatlist.find(session => session.user.name === msg.from);
            result.messages.push({
                content: msg.text,
                date: new Date(),
                self: false
            })



        },

        // 从localStorage 中获取数据
        //initData(state) {
        //state.user = [nk]
        ///  let data = localStorage.getItem('vue-chat');
        //if (data) {
        //       state.chatlist = JSON.parse(data);
        ///   }
        // },
        // 获取搜索值
        search(state, value) {
            state.searchText = value
        },
        // 得知用户当前选择的是哪个对话。便于匹配对应的对话框
        selectSession(state, value) {
            state.selectId = value
        },
        // 得知用户当前选择的是哪个好友。
        selectFriend(state, value) {
            state.selectFriendId = value
        },
        // 得知用户当前选择的是哪个医生。
        selectDoctor(state, value) {
            state.selectDoctorId = value
        },
        // 发送信息
        sendMessage(state, msg) {
            let result = state.chatlist.find(session => session.id === state.selectId);
            const user = JSON.parse(localStorage.getItem('user'));


            let message = { from: user.uname, to: result.user.name, content: msg.content }
            WebSocketService.sendMessage(message);

            result.messages.push({
                content: msg.content,
                date: new Date(),
                self: true
            });
            axios.post('http://localhost:9966/chat/saveMessage', {
                
                    from: user.uname,
                    to: result.user.name,
                    message: msg.content
            }, {
                headers: {
                    'Content-Type': 'application/json'
                }
            }).catch(error => {
                console.log(error)
            });
        },

        // 选择好友后,点击发送信息。判断在聊天列表中是否有该好友,有的话跳到该好友对话。没有的话
        // 添加该好友的对话 并置顶
        send(state) {
            let result = state.friendlist.find(friend => friend.id === state.selectFriendId)
            let msg = state.chatlist.find(msg => msg.user.name === result.remark)
            if (!msg) {
                state.selectId = 1
                for (let i = 0; i < state.chatlist.length; i++) {
                    state.chatlist[i].id++;
                    state.chatlist[i].index++;
                }
                state.chatlist.unshift({
                    id: 1,
                    user: {
                        name: result.remark,
                        img: result.img
                    },
                    messages: [
                        {
                            content: '已经置顶聊天,可以给我发信息啦!',
                            date: new Date()
                        }
                    ],
                    index: 1
                })
            } else {
                state.selectId = msg.index
                router.push({ path: '/friends' })
            }
        },

        //医生
        sendDo(state) {
            let result = state.doctor.find(doctor => doctor.id === state.selectDoctorId)
            let msg = state.chatlist.find(msg => msg.user.name === result.remark)
            if (!msg) {
                state.selectId = 1
                for (let i = 0; i < state.chatlist.length; i++) {
                    state.chatlist[i].id++;
                    state.chatlist[i].index++;
                }
                state.chatlist.unshift({
                    id: 1,
                    user: {
                        name: result.remark,
                        img: result.img
                    },
                    messages: [
                        {
                            content: '已经置顶聊天,可以给我发信息啦!',
                            date: new Date()
                        }
                    ],
                    index: 1
                })
            } else {
                state.selectId = msg.index
                router.push({ path: '/friends' })
            }
        }

基本上每个函数上面都有注释,我就不赘述了。简单的提几个函数,一个是接收webSocket返回数据的函数addMessagesToList,这个用来接收每次聊天的返回值,并用来push进message列表

一个是send(), 这个函数用来当点击朋友时,如果已经创建聊天,它会自动跳转到聊天,否则它自动创建一个新聊天。

getters

getters: {
        // 筛选出含有搜索值的聊天列表
        searchedChatlist(state) {
            let sessions = state.chatlist.filter(sessions => sessions.user.name.includes(state.searchText));
            return sessions
        },
        // 筛选出含有搜索值的好友列表
        searchedFriendlist(state) {
            let friends = state.friendlist.filter(friends => friends.remark.includes(state.searchText));
            return friends
        },
        // 筛选出含有搜索值的医生列表
        searchedDoctor(state) {
            let doctor = state.doctor.filter(doctor => doctor.remark.includes(state.searchText));
            return doctor
        },
        // 通过当前选择是哪个对话匹配相应的对话
        selectedChat(state) {
            let session = state.chatlist.find(session => session.id === state.selectId);
            return session
        },
        // 通过当前选择是哪个好友匹配相应的好友
        selectedFriend(state) {
            let friend = state.friendlist.find(friend => friend.id === state.selectFriendId);
            return friend
        },
        // 通过当前选择是哪个好友匹配相应的医生
        selectedDoctor(state) {
            let doctor = state.doctor.find(doctor => doctor.id === state.selectDoctorId);
            return doctor
        },
        messages(state) {
            let session = state.chatlist.find(session => session.id === state.selectId);
            return session.messages
        }
    },

actions

 search: ({ commit }, value) => {
            setTimeout(() => {
                commit('search', value)
            }, 100)
        },
        selectSession: ({ commit }, value) => commit('selectSession', value),
        selectFriend: ({ commit }, value) => commit('selectFriend', value),
        selectDoctor: ({ commit }, value) => commit('selectDoctor', value),
        sendMessage: ({ commit }, msg) => commit('sendMessage', msg),
        send: ({ commit }) => commit('send'),
        sendDo: ({ commit }) => commit('sendDo'),

这两部分都没什么好说的,固定套路

监听

用来监听当前选中对话

// 监听聊天列表的值, 发生变化就保存在localStorage中
store.watch(
    (state) => state.chatlist,
    (val) => {
        localStorage.setItem('vue-chat', JSON.stringify(val));
    },
    {
        deep: true
    }
)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值