Vue Cli 3项目使用融云IM实现聊天功能的方法


Posted in Javascript onApril 19, 2019

介绍:前台使用vue开发的单页面,后台使用ant design pro单页面,实现手机端和后台聊天功能。

效果如图(PC+移动):

Vue Cli 3项目使用融云IM实现聊天功能的方法

Vue Cli 3项目使用融云IM实现聊天功能的方法

一、申请融云账号(token、appKey)

建议先看教程:sdk使用介绍

过一遍教程,接下来开始写

二、引入融云IM

如图:

Vue Cli 3项目使用融云IM实现聊天功能的方法

位置:public/index.html,引入

<script src="https://cdn.ronghub.com/RongIMLib-2.3.5.min.js"></script>

三、可以正常使用RongIMLib其自带方法了

app.vue 不是全代码(因为只是连接)

created () { //生命周期函数-可发起求
 let that = this
 //融云初始化
 RongIMLib.RongIMClient.init('4z3hrv4ovrt'); //------------------------------重要填写appkey
 that.beforeIm() //设置监听,必须先设置监听,再连接
 that.nowIm() //连接融云
 },
 methods: {
 ...mapMutations({ //读取最新消息列表,并设置----------------------------重要
  getAnswer:'getAnswer'
 }),
 beforeIm(){
  let that = this
  // 连接状态监听器
  RongIMClient.setConnectionStatusListener({
   onChanged: function (status) {
    // status 标识当前连接状态
    switch (status) {
     case RongIMLib.ConnectionStatus.CONNECTED:
      console.log('链接成功');
      break;
     case RongIMLib.ConnectionStatus.CONNECTING:
      console.log('正在链接');
      break;
     case RongIMLib.ConnectionStatus.DISCONNECTED:
      console.log('断开连接');
      break;
     case RongIMLib.ConnectionStatus.KICKED_OFFLINE_BY_OTHER_CLIENT:
      console.log('其他设备登录');
      break;
     case RongIMLib.ConnectionStatus.DOMAIN_INCORRECT:
      console.log('域名不正确');
      break;
     case RongIMLib.ConnectionStatus.NETWORK_UNAVAILABLE:
      console.log('网络不可用');
      break;
    }
   }
  });

  // 消息监听器
  RongIMClient.setOnReceiveMessageListener({
   // 接收到的消息
   onReceived: function (message) {
    // 判断消息类型
    switch(message.messageType){
     case RongIMClient.MessageType.TextMessage:
      // message.content.content => 文字内容
      //----------------------------重要-------把获取的消息存放在store中,全局公用homeIm.vue要使用
      console.log('8080',message,message.content.content)
      that.getAnswer(message.content)
      break;
     case RongIMClient.MessageType.VoiceMessage:
      // message.content.content => 格式为 AMR 的音频 base64
      break;
     case RongIMClient.MessageType.ImageMessage:
      // message.content.content => 图片缩略图 base64
      // message.content.imageUri => 原图 URL
      break;
     case RongIMClient.MessageType.LocationMessage:
      // message.content.latiude => 纬度
      // message.content.longitude => 经度
      // message.content.content => 位置图片 base64
      break;
     case RongIMClient.MessageType.RichContentMessage:
      // message.content.content => 文本消息内容
      // message.content.imageUri => 图片 base64
      // message.content.url => 原图 URL
      break;
     case RongIMClient.MessageType.InformationNotificationMessage:
      // do something
      break;
     case RongIMClient.MessageType.ContactNotificationMessage:
      // do something
      break;
     case RongIMClient.MessageType.ProfileNotificationMessage:
      // do something
      break;
     case RongIMClient.MessageType.CommandNotificationMessage:
      // do something
      break;
     case RongIMClient.MessageType.CommandMessage:
      // do something
      break;
     case RongIMClient.MessageType.UnknownMessage:
      // do something
      break;
     default:
      // do something
    }
   }
  });
 },
 nowIm(){
 //自己的token------从接口获取,写到缓存
  var token = JSON.parse(localStorage.getItem('userInfo')).IMUser.token//"WzrthC5f4UfuiI7dIwCQ5fwtGfqCdobpowIZkcQnj8PQOQuAJb/nIi1ayzGFwJguvbQZxbJH3x0=";
  RongIMClient.connect(token, {
   onSuccess: function(userId) {
    console.log('Connect successfully. ' + userId);
   },
   onTokenIncorrect: function() {
    console.log('token 无效');
   },
   onError: function(errorCode){
    var info = '';
    switch (errorCode) {
     case RongIMLib.ErrorCode.TIMEOUT:
      info = '超时';
      break;
     case RongIMLib.ConnectionState.UNACCEPTABLE_PAROTOCOL_VERSION:
      info = '不可接受的协议版本';
      break;
     case RongIMLib.ConnectionState.IDENTIFIER_REJECTED:
      info = 'appkey不正确';
      break;
     case RongIMLib.ConnectionState.SERVER_UNAVAILABLE:
      info = '服务器不可用';
      break;
    }
    console.log(info);
   }
  });
 }
 },

main.js 代码

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './assets/style.css' // 外部static样式 ------重要
import './assets/js/rem.js' //rem适配 ------重要
import my from './assets/js/lbc.js' //------不重要 ---自定义全局方法

import HomeNews from './components/HomeNews.vue' //自定义组件 ------重要
Vue.component('HomeNews',HomeNews)

Vue.prototype.$my=my //------不重要 ---自定义全局方法 使用 this.$my.xxx
Vue.config.productionTip = false

new Vue({
 router,
 store,
 render: h => h(App)
}).$mount('#app')

store.js 全代码

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
const API_PROXY = 'https://bird.ioliu.cn/v1/?url='; //代理

Vue.use(Vuex)
export default new Vuex.Store({
 state: {
 answer:[]
 },
 getters: {
 },
 mutations: {
 getAnswer (state, playload) {//--------------重要
  let say ={ //自定义消息组件所需参数
   type:1,
   css:'left',
   txt:playload.content,
   date:'',
   headImg:playload.extra
  }
  state.answer.push(say)
  console.log(playload)
 },
 },
 actions: {
 }
})

homeIm.vue

//一如以往,不废话,直接代码
<template>
 <div class="homeIm" id='homeIm'>
 //----------------------------------------------------重要-------------------自定义消息组件,下面会贴码
 <home-news v-for="(item ,index) in answer" :key='index' :item='item' :data='item'></home-news>

 <div class="posFix bottom0 left0 flex justsa alic w100 bgf " style="min-height:.6rem;">
  <img src="../assets/images/mike.png" class="mike pl10 pr10"/>
  <van-field v-model="say" placeholder="请输入" class="flex1 border borRad" />
  <van-button size="large " @click="send" type='info' class="button borRad ml10 mr10" :disabled ='say?false:true'>确定</van-button>
 </div>
 
 </div>
</template>

<script>
import Vue from "vue";
import { Field ,Button } from "vant";
import router from "../router.js";
import axios from "axios";
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'


const arr = [ Field ,Button];
arr.map(e => {
 //动态生成组件
 Vue.use(e);
});

export default {
 data() {
 return { 
  say:'小仙女,你好鸭'
 };
 },
 name: "homeIm",
 props: {
 msg: String
 },
 created() {
 //this.getChatRecord() //获取聊天记录,要钱
 this.$nextTick(() => {//------------------------重要-------有消息就滚动到底部-----------------------
  let list = document.getElementById('homeIm')
  document.documentElement.scrollTop = list.scrollHeight
  //如不行,请尝试-> list.scrollTop = list.scrollHeight
  })
 },
 computed:{
 ...mapState({
  answer:"answer",
 }),

 },
 watch: { //------------------------重要-------有消息就滚动到底部-----------------------
 answer() {
  this.$nextTick(() => {
  let list = document.getElementById('homeIm')
  document.documentElement.scrollTop = list.scrollHeight
  //如不行,请尝试-> list.scrollTop = list.scrollHeight
  })
 }
 },
 methods: {
 send() {
  let that = this
  let msg = new RongIMLib.TextMessage({ content: that.say, extra: 'https://img.52z.com/upload/news/image/20171120/20171120080335_21404.jpg' });
  let conversationType = RongIMLib.ConversationType.PRIVATE; // 单聊, 其他会话选择相应的消息类型即可
  let targetId = JSON.parse(localStorage.getItem('userInfo')).IMUser.assistantId; // 目标 Id

  RongIMClient.getInstance().sendMessage(conversationType, targetId, msg, {
   onSuccess: function (message) {
    // message 为发送的消息对象并且包含服务器返回的消息唯一 Id 和发送消息时间戳
    console.log('Send successfully',message,message.content.content);
    let say = {
     type:1,
     css:'right',
     txt:message.content.content,
     headImg:'https://img.52z.com/upload/news/image/20171120/20171120080335_21404.jpg'
    }
    that.answer.push(say)
    that.say = ''
   },
   onError: function (errorCode, message) {
    let info = '';
    switch (errorCode) {
     case RongIMLib.ErrorCode.TIMEOUT:
      info = '超时';
      break;
     case RongIMLib.ErrorCode.UNKNOWN:
      info = '未知错误';
      break;
     case RongIMLib.ErrorCode.REJECTED_BY_BLACKLIST:
      info = '在黑名单中,无法向对方发送消息';
      break;
     case RongIMLib.ErrorCode.NOT_IN_DISCUSSION:
      info = '不在讨论组中';
      break;
     case RongIMLib.ErrorCode.NOT_IN_GROUP:
      info = '不在群组中';
      break;
     case RongIMLib.ErrorCode.NOT_IN_CHATROOM:
      info = '不在聊天室中';
      break;
    }
    console.log('发送失败: ' + info + errorCode);
   }
  });
 },
 getChatRecord(){
  let conversationType = RongIMLib.ConversationType.PRIVATE; //单聊, 其他会话选择相应的消息类型即可
  let targetId = '2'; // 想获取自己和谁的历史消息,targetId 赋值为对方的 Id
  let timestrap = null; // 默认传 null,若从头开始获取历史消息,请赋值为 0, timestrap = 0;
  let count = 20; // 每次获取的历史消息条数,范围 0-20 条,可以多次获取
  RongIMLib.RongIMClient.getInstance().getHistoryMessages(conversationType, targetId, timestrap, count, {
   onSuccess: function(list, hasMsg) {
    // list => Message 数组。
    // hasMsg => 是否还有历史消息可以获取。
    console.log('历史纪录',list, hasMsg)
   },
   onError: function(error) {
    console.log('GetHistoryMessages, errorcode:' + error);
   }
  });
 }
 },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.mike{
 width: .3rem;height: .3rem;
}
.border{border:1px solid #ccc;}
.button{
 width: .8rem;height: .46rem;
}
.homeIm{padding-bottom: .7rem;}
</style>

homeNews.vue 全代码

<template>
 <div class="homeNews">
  <!-- 1:文字,2:红包,3:文章 ,css:类型 -->
  <div v-if="data.type == 1&&data.css == 'left'">
   <div class="colora1 fz12 lh40 pt10">{{data.date}}</div>
   <div class="flex pl20 pr20 borBox">
   <img :src="data.headImg" class="head borRad">
   <div class="frame borRad bgf lh24 fz16 tl color3 pl10 pr10 pt10 pb10 borBox w250 ml15 posRel">
    {{data.txt}}
   </div>
   </div>
  </div>
  <router-link to="/homeRedBag" v-else-if="data.type == 2&&data.css == 'left'">
   <div class="colora1 fz12 lh40 pt10">{{data.date}}</div>
   <div class="flex pl20 pr20 borBox">
   <img :src="data.headImg" class="head borRad">
   <div class="frame borRad bgf9 lh24 fz16 tl colorF w200 ml15 posRel redFrame">
    <div class="flex alic pl10 pr10 pt10 pb10 borBox">
    <img src="../assets/images/redTabs.png" class="redTabs"/>
    <span class="pl10">{{data.title}}</span>
    </div>
    <div class="fz12 color6 bgf pl15 borBox txt">{{data.txt}}</div>
   </div>
   </div>
  </router-link>
  <router-link to="/homeArticle" v-else-if="data.type == 3&&data.css == 'left'">
   <div class="colora1 fz12 lh40 pt10">{{data.date}}</div>
   <div class="flex pl20 pr20 borBox">
   <img :src="data.headImg" class="head borRad">
   <div class="frame borRad bgf fz16 tl color3 pl10 pr10 pt10 pb10 borBox w250 ml15 posRel">
    <div class="fz20 txt2 mb10 lh30">{{data.title}}</div>
    <div class="flex justsa alic">
    <div class="colora1 txt2 flex1 lh20">{{data.txt}}</div>
    <img :src="data.banner" class="banner"/>
    </div>
   </div>
   </div>
  </router-link>
  <div v-if="data.type == 1&&data.css == 'right'">
  <div class="colora1 fz12 lh40 pt10">{{data.date}}</div>
  <div class="flex pl20 pr20 borBox juste">
   <div class="frame-right borRad bgf lh24 fz16 tl color3 pl10 pr10 pt10 pb10 borBox w250 mr15 posRel">
   {{data.txt}}
   </div>
   <img :src="data.headImg" class="head borRad">
  </div>
  </div>

 </div>
</template>
<script>
import Vue from "vue";
import router from "../router.js";
export default {
 name: "homeNews",
 props:['data'],
 data() {
 return {
 };
 },
 created() {
 console.log()
 },
 methods: {
 }
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.head {
 width: 0.36rem;
 height: 0.36rem;
}
.frame::before {
 display: block;
 content: '';
 width: 0px; /* 宽高设置为0,很重要,否则达不到效果 */
 height: 0px;
 border: .10rem solid #fff;
 border-bottom-color: transparent; /* 设置透明背景色 */
 border-top-color: transparent;
 border-left-color: transparent;
 position: absolute;left:-.2rem;top:.1rem;
}
.frame-right::before{
 display: block;
 content: '';
 width: 0px; /* 宽高设置为0,很重要,否则达不到效果 */
 height: 0px;
 border: .10rem solid #fff;
 border-bottom-color: transparent; /* 设置透明背景色 */
 border-top-color: transparent;
 border-right-color: transparent;
 position: absolute;right:-.2rem;top:.1rem;
}
.redFrame::before{
 display: block;
 content: '';
 width: 0px; /* 宽高设置为0,很重要,否则达不到效果 */
 height: 0px;
 border: .10rem solid #F99F3E;
 border-bottom-color: transparent; /* 设置透明背景色 */
 border-top-color: transparent;
 border-left-color: transparent;
 position: absolute;left:-.2rem;top:.1rem;
}
.redFrame-right::before{
 display: block;
 content: '';
 width: 0px; /* 宽高设置为0,很重要,否则达不到效果 */
 height: 0px;
 border: .10rem solid #F99F3E;
 border-bottom-color: transparent; /* 设置透明背景色 */
 border-top-color: transparent;
 border-left-color: transparent;
 position: absolute;right:-.2rem;top:.1rem;
}
.w250{max-width: 2.5rem;}
.w200{max-width: 2rem;}
.redTabs{
 width: .32rem;
 height:.39rem;
}
.txt{
 border-bottom-left-radius: .05rem;
 border-bottom-right-radius: .05rem;
}
.banner{width: .4rem;height: .4rem;}
</style>
style.css 我自己的样式表
@charset "utf-8";
/* CSS Document 刘白超修改于2019/3/10*/
html,body{height: 100%;width: 100%;word-wrap:break-word;}
*{margin: 0;padding: 0;}
.tc{text-align: center}
.tr{text-align: right}
.tl{text-align: left}
.vm{vertical-align: middle;}
.vs{vertical-align: sub;}
.fl{float: left;}
.fr{float: right;}
.fz24{font-size: .24rem;}
.fz20{font-size: .2rem;}
.fz18{font-size: .18rem;}
.fz16{font-size: .16rem;}
.fz14{font-size: .14rem;}
.fz12{font-size: .12rem;}
.fw{font-weight: 600;}
.mr5{margin-right: .05rem}
.mr10{margin-right: .10rem}
.mr15{margin-right: .15rem}
.mr20{margin-right: .20rem}
.ml5{margin-left:.05rem;}
.ml10{margin-left:.10rem;}
.ml15{margin-left:.15rem;}
.ml20{margin-left:.20rem;}
.ml24{margin-left:.24rem;}
.mt40{margin-top:.40rem;}
.mt20{margin-top: .20rem;}
.mt15{margin-top: .15rem;}
.mt10{margin-top: .10rem;}
.mt5{margin-top: .05rem;}
.mb5{margin-bottom: .05rem;}
.mb10{margin-bottom: .10rem;}
.mb15{margin-bottom: .15rem;}
.mb20{margin-bottom: .20rem;}
.pt5{padding-top: .05rem;}
.pt10{padding-top: .10rem;}
.pt15{padding-top: .15rem;}
.pt20{padding-top: .20rem;}
.pt30{padding-top: .30rem;}
.pb5{padding-bottom: .05rem;}
.pb10{padding-bottom: .10rem;}
.pb15{padding-bottom: .15rem;}
.pb20{padding-bottom: .20rem;}
.pl5{padding-left: .05rem;}
.pl10{padding-left: .10rem;}
.pl15{padding-left: .15rem;}
.pl20{padding-left: .20rem;}
.pl30{padding-left: .30rem;}
.pr5{padding-right: .05rem;}
.pr10{padding-right: .10rem;}
.pr15{padding-right: .15rem;}
.pr20{padding-right: .20rem;}
.pr30{padding-right: .30rem;}
.bgef{background: #EFEFEF;}
.bgf{background: #fff;}
.bgf9{background: #F99F3E}
.ee {background: #eee;}
.bg259{background:#259DFF !important}
.colordd{color: #DD4D41}
.colorf9 {color: #ff9800;}
.colore5{color: #e51c23;}
.colorF{color: #fff;}
.color3{color: #333;}
.color6{color: #666;}
.color9{color: #999;}
.colora1{color:#a1a1a1}
.color259{color:#259DFF}
.color005{color:#00559B}
.colorf3{color:#F3665E}
.lh24{line-height: .24rem}
.lh20{line-height: .20rem;}
.lh30{line-height: .30rem;}
.lh40{line-height: .40rem;}
.lh50{line-height: .50rem;}
.lh60{line-height: .60rem;}
.hide{display: none}
.show{display: block}
.inline{display: inline-block;}
.indent2{text-indent: 2em;}
.txt2{
 overflow : hidden;
 text-overflow: ellipsis;
 display: -webkit-box;
 -webkit-line-clamp: 2;
 -webkit-box-orient: vertical;
}
.wn{white-space:nowrap;}
.flex{display: flex;}
.flex1{flex:1;}
.colu{flex-direction: column;}
.justc{justify-content: center;}
.justs{justify-content: space-between}/*两端对齐*/
.justsa{justify-content: space-around}/*分散对齐*/
.juste{justify-content: flex-end;}
.alic{align-items: center}
.wrap{flex-wrap:wrap}
.childEnd{align-self:flex-end;}
.posAbs{position: absolute;}
.posRel{position: relative;}
.posFix{position: fixed;}
.top0{top:0;}
.bottom0{bottom:0;}
.left0{left:0;}
.right0{right: 0;}
.w100{width: 100%}
.h100{height: 100%}
.borBox{box-sizing: border-box;}
.borderte0{border-top:1px solid #e0e0e0; }
.borderbe0{border-bottom:1px solid #e0e0e0; }
.borRad{border-radius:.05rem;}
.over{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}
.overH{overflow: hidden}
.clear{zoom:1;}
.clear:after{content: "\0020";display: block;height: 0;clear: both;}
.mask{width: 100%;height: 100%;background: rgba(20, 20, 20, 0.5);position: fixed;z-index: 5;top: 0;left: 0;}
.cursor{cursor: pointer;}
.noClick{pointer-events: none;}
li{list-style:none;}
a{text-decoration:none;color:#555;}
a:hover{color:#555;}
img{display:block;vertical-align:middle;}
a img,fieldset{border:0;}
i,em{font-style:normal}
b,strong,th{font-weight:100;}
input,textarea,select{outline:none;}
textarea{resize:none;}
table{border-collapse:collapse;}
.btn{
 width: calc(100% - .54rem);
 background: #259DFF;
 font: .2rem/.5rem "";
 text-align: center;
 color: #fff;
 border-radius: 5px;
 margin-left: .27rem;
}
rem.js rem自适应单位
//例如设计稿为375,最大宽度为750,则为(375,750)
!function(e,t){function n(){var n=l.getBoundingClientRect().width;t=t||540,n>t&&(n=t);var i=100*n/e;r.innerHTML="html{font-size:"+i+"px;}"}var i,d=document,o=window,l=d.documentElement,r=document.createElement("style");if(l.firstElementChild)l.firstElementChild.appendChild(r);else{var a=d.createElement("div");a.appendChild(r),d.write(a.innerHTML),a=null}n(),o.addEventListener("resize",function(){clearTimeout(i),i=setTimeout(n,300)},!1),o.addEventListener("pageshow",function(e){e.persisted&&(clearTimeout(i),i=setTimeout(n,300))},!1),"complete"===d.readyState?d.body.style.fontSize="16px":d.addEventListener("DOMContentLoaded",function(e){d.body.style.fontSize="16px"},!1)}(375,640);

完了,okk,文中所需icon,请自行到阿里icon下载

结尾:项目中需要配置rem。

总结

以上所述是小编给大家介绍的Vue Cli 3项目使用融云IM实现聊天功能的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
完美解决JS中汉字显示乱码问题(已解决)
Dec 27 Javascript
上传图片js判断图片尺寸和格式兼容IE
Sep 01 Javascript
javascript引擎长时间独占线程造成卡顿的解决方案
Dec 03 Javascript
Node.js的npm包管理器基础使用教程
May 26 Javascript
详解PHP中pathinfo()函数导致的安全问题
Jan 05 Javascript
加载 vue 远程代码的组件实例详解
Nov 20 Javascript
Element输入框带历史查询记录的实现示例
Jan 15 Javascript
JavaScript数组去重实现方法小结
Jan 17 Javascript
JavaScript 正则应用详解【模式、欲查、反向引用等】
May 13 Javascript
浅析微信小程序自定义日历组件及flex布局最后一行对齐问题
Oct 29 Javascript
详解如何在Canvas中添加事件的方法
Apr 17 Javascript
如何开发一个渐进式Web应用程序PWA
May 10 Javascript
详解vue-cli+es6引入es5写的js(两种方法)
Apr 19 #Javascript
vue中使用vue-cli接入融云实现即时通信
Apr 19 #Javascript
浅谈Javascript中的对象和继承
Apr 19 #Javascript
详解如何在Vue项目中导出Excel
Apr 19 #Javascript
vue cli使用融云实现聊天功能的实例代码
Apr 19 #Javascript
详解vue中使用微信jssdk
Apr 19 #Javascript
vue router导航守卫(router.beforeEach())的使用详解
Apr 19 #Javascript
You might like
利用js调用后台php进行数据处理原码
2006/10/09 PHP
PHP编程与应用
2006/10/09 PHP
在任意字符集下正常显示网页的方法二(续)
2007/04/01 PHP
php 404错误页面实现代码
2009/06/22 PHP
ThinkPHP的Widget扩展实例
2014/06/19 PHP
PHP GD库生成图像的几个函数总结
2014/11/19 PHP
PHP实现的简单适配器模式示例
2017/06/22 PHP
你的编程语言可以这样做吗?
2006/09/07 Javascript
jQuery图片预加载 等比缩放实现代码
2011/10/04 Javascript
可兼容IE的获取及设置cookie的jquery.cookie函数方法
2013/09/02 Javascript
JavaScript DOM节点添加示例
2014/07/16 Javascript
全面解析多种Bootstrap图片轮播效果
2016/05/27 Javascript
JS及PHP代码编写八大排序算法
2016/07/12 Javascript
详解js中call与apply关键字的作用
2016/11/21 Javascript
jQuery实现淡入淡出的模态框
2017/02/09 Javascript
Easyui ueditor 整合解决不能编辑的问题(推荐)
2017/06/25 Javascript
使用cookie绕过验证码登录的实现代码
2017/10/12 Javascript
原生JS实现列表内容自动向上滚动效果
2019/05/22 Javascript
js canvas实现星空连线背景特效
2019/11/01 Javascript
[03:02]2020完美世界城市挑战赛(秋季赛)总决赛回顾
2021/03/11 DOTA
Python selenium文件上传方法汇总
2020/11/19 Python
Python yield 使用方法浅析
2017/05/20 Python
利用selenium 3.7和python3添加cookie模拟登陆的实现
2017/11/20 Python
pycharm new project变成灰色的解决方法
2019/06/27 Python
Django REST Framework序列化外键获取外键的值方法
2019/07/26 Python
Pycharm快捷键配置详细整理
2020/10/13 Python
Python实现简单的猜单词小游戏
2020/10/28 Python
英国领先的珍珠首饰品牌:Orchira
2016/09/11 全球购物
英国和爱尔兰的自炊式豪华度假小屋:Rural Retreats
2018/06/08 全球购物
Fenty Beauty官网:蕾哈娜创立的美妆品牌
2021/01/07 全球购物
文员的职业生涯规划发展方向
2014/02/08 职场文书
竞选班干部演讲稿600字
2014/08/20 职场文书
自荐信格式范文
2015/03/04 职场文书
小学语文教学随笔
2015/08/14 职场文书
quickjs 封装 JavaScript 沙箱详情
2021/11/02 Javascript
Spring Cloud Netflix 套件中的负载均衡组件 Ribbon
2022/04/13 Java/Android