大理一装修设计 發表於 2019-7-16 14:42:00

angular版聊天室|仿微信界面IM聊天|NG2+Node聊天实例

<h3 id="一项目简介">一、项目介绍</h3>
<p><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif; background-color: rgba(153, 204, 255, 1)">运用angular+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcPop等技术实现开发的仿微信angular版聊天室angular-chatroom实例项目,实现了下拉刷新、聊天消息右键菜单、发送消息、表情(动图),图片、视频预览,红包打赏等功能。</span></p>
<h3 id="一项目简介">二、技术实现</h3>
<ul>
<li><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif">MVVM框架:angular8.0 / @angular/cli</span></li>
<li><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif">状态管理:@ngrx/store / rxjs</span></li>
<li><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif">地址路由:@angular/router</span></li>
<li><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif">弹窗组件:wcPop</span></li>
<li><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif">打包工具:webpack 2.0</span></li>
<li><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif">环境配置:node.js + cnpm</span></li>
<li><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif">图片预览:previewImage</span></li>
<li><span style="font-size: 12px; font-family: &quot;comic sans ms&quot;, sans-serif">轮播滑动:swiper</span></li>
</ul>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span>"name": "angular-chatroom"<span style="color: rgba(0, 0, 0, 1)">,
</span>"contact": "QQ:282310962 、 wx:xy190310"<span style="color: rgba(0, 0, 0, 1)">,

</span>"dependencies"<span style="color: rgba(0, 0, 0, 1)">: {
    </span>"@angular/animations": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/common": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/compiler": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/core": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/forms": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/platform-browser": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/platform-browser-dynamic": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/router": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"rxjs": "~6.4.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"tslib": "^1.9.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"zone.js": "~0.9.1"<span style="color: rgba(0, 0, 0, 1)">
},
</span>"devDependencies"<span style="color: rgba(0, 0, 0, 1)">: {
    </span>"@angular-devkit/build-angular": "~0.800.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/cli": "~8.0.3"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/compiler-cli": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@angular/language-service": "~8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@ngrx/store": "^8.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@types/jasmine": "~3.3.8"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@types/jasminewd2": "~2.0.3"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@types/node": "~8.9.4"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"@types/swiper": "^4.4.3"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"codelyzer": "^5.0.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"jasmine-core": "~3.4.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"jasmine-spec-reporter": "~4.2.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"jquery": "^2.2.3"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"karma": "~4.1.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"karma-chrome-launcher": "~2.2.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"karma-coverage-istanbul-reporter": "~2.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"karma-jasmine": "~2.0.1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"karma-jasmine-html-reporter": "^1.4.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"swiper": "^4.5.0"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"typescript": "~3.4.3"<span style="color: rgba(0, 0, 0, 1)">
}
}</span></pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142412905-1489665589.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142447475-1863793906.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142459275-1985853626.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142509425-566268077.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142515924-898971192.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142524245-751774554.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142532414-1972598761.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142544020-856448062.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142553109-636449688.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142609147-243572109.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142645178-298241915.png"></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716142658898-916627120.png"></p>
<p><strong>◆ App主页面模板、app-routing路由地址配置</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="weChatIM__panel clearfix"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="we__chatIM-wrapper flexbox flex__direction-column"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 顶部 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">header-bar</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">header-bar</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      
      <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 主页面 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">div </span><span style="color: rgba(255, 0, 0, 1)">class</span><span style="color: rgba(0, 0, 255, 1)">="wcim__container flex1"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
            <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">router-outlet</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">router-outlet</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>

      <span style="color: rgba(0, 128, 0, 1)">&lt;!--</span><span style="color: rgba(0, 128, 0, 1)"> 底部 </span><span style="color: rgba(0, 128, 0, 1)">--&gt;</span>
      <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">tab-bar</span><span style="color: rgba(0, 0, 255, 1)">&gt;&lt;/</span><span style="color: rgba(128, 0, 0, 1)">tab-bar</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
    <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">div</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
*angular/router路由配置
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">

import { NgModule } from </span>'@angular/core'<span style="color: rgba(0, 0, 0, 1)">
import { Routes, RouterModule } from </span>'@angular/router'

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引入路由验证</span>
import { Auth } from '../views/auth/auth'

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 引入页面组件</span>
import { NotFoundComponent } from '../components/404'<span style="color: rgba(0, 0, 0, 1)">
import { LoginComponent } from </span>'../views/auth/login'<span style="color: rgba(0, 0, 0, 1)">
import { RegisterComponent } from </span>'../views/auth/register'<span style="color: rgba(0, 0, 0, 1)">
import { IndexComponent } from </span>'../views/index'<span style="color: rgba(0, 0, 0, 1)">
import { ContactComponent } from </span>'../views/contact'<span style="color: rgba(0, 0, 0, 1)">
import { UinfoComponent } from </span>'../views/contact/uinfo'<span style="color: rgba(0, 0, 0, 1)">
import { UcenterComponent } from </span>'../views/ucenter'<span style="color: rgba(0, 0, 0, 1)">
import { GroupChatComponent } from </span>'../views/chat/group-chat'<span style="color: rgba(0, 0, 0, 1)">
import { GroupInfoComponent } from </span>'../views/chat/group-info'<span style="color: rgba(0, 0, 0, 1)">
import { SingleChatComponent } from </span>'../views/chat/single-chat'<span style="color: rgba(0, 0, 0, 1)">


export const routes: Routes </span>=<span style="color: rgba(0, 0, 0, 1)"> [
{
    path: </span>'', redirectTo: 'index', pathMatch: 'full'<span style="color: rgba(0, 0, 0, 1)">,
    data: { showHeader: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, showTabBar: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 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, 0, 1)">{
    path: </span>'login'<span style="color: rgba(0, 0, 0, 1)">, component: LoginComponent,
},
{
    path: </span>'register'<span style="color: rgba(0, 0, 0, 1)">, component: RegisterComponent,
},

</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, 0, 1)">{
    path: </span>'index'<span style="color: rgba(0, 0, 0, 1)">, component: IndexComponent, canActivate: ,
    data: { showHeader: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, showTabBar: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> },
},
{
    path: </span>'contact'<span style="color: rgba(0, 0, 0, 1)">, component: ContactComponent, canActivate: ,
    data: { showHeader: </span><span style="color: rgba(0, 0, 255, 1)">true</span>, showTabBar: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)"> },
},
{
    path: </span>'contact/uinfo'<span style="color: rgba(0, 0, 0, 1)">, component: UinfoComponent
},
{
    path: </span>'ucenter'<span style="color: rgba(0, 0, 0, 1)">, component: UcenterComponent, canActivate: ,
    data: { showHeader: </span><span style="color: rgba(0, 0, 255, 1)">false</span>, showTabBar: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 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, 0, 1)">{
    path: </span>'chat/group-chat'<span style="color: rgba(0, 0, 0, 1)">, component: GroupChatComponent, canActivate:
},
{
    path: </span>'chat/single-chat'<span style="color: rgba(0, 0, 0, 1)">, component: SingleChatComponent, canActivate:
},
{
    path: </span>'chat/group-info'<span style="color: rgba(0, 0, 0, 1)">, component: GroupInfoComponent, canActivate:
},

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 404</span>
<span style="color: rgba(0, 0, 0, 1)">{
    path: </span>'**'<span style="color: rgba(0, 0, 0, 1)">, component: NotFoundComponent,
},

</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, 0, 1)">];

@NgModule({
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> imports: ,</span>
imports: ,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">开启hash模式</span>
<span style="color: rgba(0, 0, 0, 1)">exports: ,
providers:
})
export class AppRoutingModule {}</span></pre>
</div>
<p><strong>◆ angular + ngrx/store页面状态管理</strong></p>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716143402040-1412011262.png"></p>
<p><strong>◆ angular登录、注册验证</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">export class LoginComponent implements OnInit {
    private formField </span>=<span style="color: rgba(0, 0, 0, 1)"> {
      tel: </span>''<span style="color: rgba(0, 0, 0, 1)">,
      pwd: </span>''<span style="color: rgba(0, 0, 0, 1)">
    }
   
    private auth: any
    constructor(
      private router: Router,
      private store: Store</span>&lt;{}&gt;<span style="color: rgba(0, 0, 0, 1)">
    ) {
      let that </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>
      <span style="color: rgba(0, 0, 255, 1)">this</span>.store.select('auth').subscribe(v =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
            console.log(v)
            that.auth </span>=<span style="color: rgba(0, 0, 0, 1)"> v;
      })
    }

    ngOnInit(): </span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.auth.token){
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.router.navigate(['/index'<span style="color: rgba(0, 0, 0, 1)">])
      }
    }

    handleSubmit(){
      let that </span>= <span style="color: rgba(0, 0, 255, 1)">this</span>

      <span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.formField.tel){
            wcPop({ content: </span>'手机号不能为空!', style: 'background:#eb5a5c;color:#fff;', time: 2<span style="color: rgba(0, 0, 0, 1)"> });
      }</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span>(!checkTel(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.formField.tel)){
            wcPop({ content: </span>'手机号格式不正确!', style: 'background:#eb5a5c;color:#fff;', time: 2<span style="color: rgba(0, 0, 0, 1)"> });
      }</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.formField.pwd){
            wcPop({ content: </span>'密码不能为空!', style: 'background:#eb5a5c;color:#fff;', time: 2<span style="color: rgba(0, 0, 0, 1)"> });
      }</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.store.dispatch(<span style="color: rgba(0, 0, 255, 1)">new</span> actions.setToken(getToken(64<span style="color: rgba(0, 0, 0, 1)">)))
            </span><span style="color: rgba(0, 0, 255, 1)">this</span>.store.dispatch(<span style="color: rgba(0, 0, 255, 1)">new</span> actions.setUser(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.formField.tel))

            wcPop({
                content: </span>'登录成功,跳转中...', style: 'background:#378fe7;color:#fff;', time: 2, shadeClose: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
                end: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
                  that.router.navigate([</span>'/index'<span style="color: rgba(0, 0, 0, 1)">])
                }
            });
      }
    }
}</span></pre>
</div>
<p><strong>◆ 编辑器核心消息处理</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> surrounds() {
    setTimeout(</span><span style="color: rgba(0, 0, 255, 1)">function</span> () { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">chrome</span>
      <span style="color: rgba(0, 0, 255, 1)">var</span> sel =<span style="color: rgba(0, 0, 0, 1)"> window.getSelection();
      </span><span style="color: rgba(0, 0, 255, 1)">var</span> anchorNode =<span style="color: rgba(0, 0, 0, 1)"> sel.anchorNode;
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!anchorNode) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (sel.anchorNode === $(".J__wcEditor") ||<span style="color: rgba(0, 0, 0, 1)">
            (sel.anchorNode.nodeType </span>=== 3 &amp;&amp; sel.anchorNode.parentNode === $(".J__wcEditor"))) {

            </span><span style="color: rgba(0, 0, 255, 1)">var</span> range = sel.getRangeAt(0<span style="color: rgba(0, 0, 0, 1)">);
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> p = document.createElement("p"<span style="color: rgba(0, 0, 0, 1)">);
            range.surroundContents(p);
            range.selectNodeContents(p);
            range.insertNode(document.createElement(</span>"br")); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">chrome</span>
            sel.collapse(p, 0<span style="color: rgba(0, 0, 0, 1)">);

            (</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> clearBr() {
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> elems = [].slice.call($(".J__wcEditor").children);
                </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> i = 0, len = elems.length; i &lt; len; i++<span style="color: rgba(0, 0, 0, 1)">) {
                  </span><span style="color: rgba(0, 0, 255, 1)">var</span> el =<span style="color: rgba(0, 0, 0, 1)"> elems;
                  </span><span style="color: rgba(0, 0, 255, 1)">if</span> (el.tagName.toLowerCase() == "br"<span style="color: rgba(0, 0, 0, 1)">) {
                        $(</span>".J__wcEditor").removeChild(el);
                  }
                }
                elems.length </span>= 0<span style="color: rgba(0, 0, 0, 1)">;
            })();
      }
    }, </span>10<span style="color: rgba(0, 0, 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)">var</span> _lastRange = <span style="color: rgba(0, 0, 255, 1)">null</span>, _sel = window.getSelection &amp;&amp;<span style="color: rgba(0, 0, 0, 1)"> window.getSelection();
</span><span style="color: rgba(0, 0, 255, 1)">var</span> _rng =<span style="color: rgba(0, 0, 0, 1)"> {
    getRange: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (_sel &amp;&amp; _sel.rangeCount &gt; 0<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> _sel.getRangeAt(0<span style="color: rgba(0, 0, 0, 1)">);
      }
    },
    addRange: </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (_lastRange) {
            _sel.removeAllRanges();
            _sel.addRange(_lastRange);
      }
    }
}

</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)">function</span><span style="color: rgba(0, 0, 0, 1)"> isEmpty() {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> var html = $editor.html();</span>
    <span style="color: rgba(0, 0, 255, 1)">var</span> html = $(".J__wcEditor"<span style="color: rgba(0, 0, 0, 1)">).html();
    html </span>= html.replace(/&lt;br[\s\/]{0,2}&gt;/ig, "\r\n"<span style="color: rgba(0, 0, 0, 1)">);
    html </span>= html.replace(/&lt;[^img].*?&gt;/ig, ""<span style="color: rgba(0, 0, 0, 1)">);
    html </span>= html.replace(/&amp;nbsp;/ig, ""<span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> html.replace(/\r\n|\n|\r/, "").replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g, "") == ""<span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1289798/201907/1289798-20190716143958013-310223433.jpg"></p>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    本文为博主原创文章,未经博主允许不得转载,欢迎大家一起交流 QQ(282310962) wx(xy190310)<br><br>
来源:https://www.cnblogs.com/xiaoyan2017/p/11194828.html
頁: [1]
查看完整版本: angular版聊天室|仿微信界面IM聊天|NG2+Node聊天实例