Ionic-wechat項目邊開發邊學(三):自定義樣式,指令,服務


摘要

上一篇文章主要介紹了一個ionic項目的標准目錄結構,header標簽的使用,以及頁面之間的切換。這篇文章實現的功能有: 消息數據的獲取, 消息列表的展示, 消息標為已讀/未讀, 主要涉及的到的知識點有:

  1. ion-list的使用
  2. ion-popup的使用
  3. 通過sass自定義樣式
  4. localStorage的使用
  5. 自定義指令和服務

先看效果圖:

功能分析

在開始之前, 最好先思考一下消息頁面的主要功能, 和大概如何實現. 這樣后面寫程序才不會亂. 我大體列了一下

消息的數據暫時用localStorage存儲, 但這不是好的方式, localStorage可能會被文件清理掉, 后面會換sqlite存儲

頁面布局

首先在'tab-message.html'中添加聊天消息的布局

<ion-view>
    <ion-content on-swipe-left="onSwipeLeft()">
        <!--這里的rj-close-back-drop是自定義指令, 后面會講是干嘛的-->
        <ion-list rj-close-back-drop>
          <ion-item class="item-avatar" on-hold="popupMessageOpthins($index)" rj-hold-active ng-repeat="message in messages">
              <img ng-src="{{message.pic}}">
              <!--這個就是來了新消息, 頭像上的小紅數字-->
              <span class="rj-sm-red-icon" ng-show="message.showHints"><p ng-bind="message.noReadMessages"></p></span>
              <h2 ng-bind="message.name"></h2>
              <p class="rj-list-p" ng-bind="message.lastMessage.content"></p>
              <span class="rj-push-right" ng-bind="message.lastMessage.time"></span>
          </ion-item>
        </ion-list>
    </ion-content>
</ion-view>

大家在試這個的時候, 由於'messages'還未定義, 先不綁定, 用實際的值代替,像這樣

<img src="img/ben.png">
<span class="rj-sm-red-icon"><p>1</p></span>
<h2>小王</h2>
<p class="rj-list-p">你在干什么?</p>
<span class="rj-push-right">12:30</span>

這樣就能看到效果了

自定義樣式

可以看到上圖有點丑, 需要我們自己修改樣式, 可以自己添加css文件link進來, 但官方推薦使用sass的方式修改, 關於sass的語法, 可以看這個, 看完就差不多可以了.

首先在項目目錄下,運行命令

$ionic setup sass
$ionic serve

運行以后, 就會對scss/ionic.app.scss文件監控, 有修改, 會自動編譯該文件, 輸出到css/ionic.app.css

所以你每次修改保存scss文件后, 瀏覽器會看到實時的效果, 非常方便.

打開scss/ionic.app.scss文件, 如下

/*
To customize the look and feel of Ionic, you can override the variables
in ionic's _variables.scss file.

For example, you might change some of the default colors:

$light:                           #fff !default;
$stable:                          #f8f8f8 !default;
$positive:                        #387ef5 !default;
$calm:                            #11c1f3 !default;
$balanced:                        #33cd5f !default;
$energized:                       #ffc900 !default;
$assertive:                       #ef473a !default;
$royal:                           #886aea !default;
$dark:                            #444 !default;
*/

// The path for our ionicons font files, relative to the built CSS in www/css
$ionicons-font-path: "../lib/ionic/fonts" !default;

可以看到官方預定義的顏色幾個顏色, 如果要修改預定義的顏色, 直接修改這里就可以了.

我們自己的樣式, 直接在后面添加. 我們在后面添加

$item-avatar-border-radius: 0;

可以發現頭像變成方的了, 那怎么知道修改這個變量呢?

打開www/lib/ionic/scss/目錄, 可以看到很多scss文件

├── _action-sheet.scss
├── _animations.scss
├── _backdrop.scss
├── _badge.scss
├── _bar.scss
├── _button-bar.scss
├── _button.scss
├── _checkbox.scss
├── _form.scss
├── _grid.scss
├── ionicons
├── ionic.scss
├── _items.scss
├── _list.scss
├── _loading.scss
├── _menu.scss
├── _mixins.scss
├── _modal.scss
...

這些都是官方的樣式文件, 找到items.scss文件, 這個就是ion-item相關的樣式, 再搜border-radius很快就能找到啦

具體的細節我就不說啦, 其它的修改都類似, 可以參考我的代碼

popup的使用

關於$ionicPopup的詳細使用, 可以參考官網

首先在controllers.js文件中添加一個controller:

.controller('messageCtrl', function($scope, $state, $ionicPopup, localStorageService, messageService) {
    $scope.popup = {
        isPopup: false,
        index: 0
    };
    $scope.onSwipeLeft = function() {
        $state.go("tab.friends");
    };
    $scope.popupMessageOpthins = function($index) {
        $scope.popup.index = $index;
        //這里通過$ionicPopup.show()方法創建了一個自定義的popup
        $scope.popup.optionsPopup = $ionicPopup.show({
            templateUrl: "templates/popup.html",
            scope: $scope,
        });
        $scope.popup.isPopup = true;
    };
    //實現標為已讀/未讀, 注意$scope.popup.optionsPopup.close()方法
    //用來關閉彈窗, 我竟然找了很久才發現這個接口
    $scope.markMessage = function() {
        var index = $scope.popup.index;
        var message = $scope.messages[index];
        if (message.showHints) {
            message.showHints = false;
            message.noReadMessages = 0;
        }else{
            message.showHints = true;
            message.noReadMessages = 1;
        }
        $scope.popup.optionsPopup.close();
        $scope.popup.isPopup = false;
        messageService.updateMessage(message);
    };

這里要注意兩點

  1. 要在routes.js中將該controll傳進去
  2. 需要通過自定義樣式, 去掉自帶的標題和按鈕
//routes.js
.state('tab.message', {
    url: '/message',
    views: {
        'tab-message': {
            templateUrl: 'templates/tab-message.html',
            controller: "messageCtrl"
        }
    }
})

自定義指令

細心的人會發現兩個問題:

  1. 彈出popup時, 聯系人列表沒有動畫效果
  2. 彈出popup后, 點擊popup以外的地方, popup不能消失, 這兩個問題, 就通過自定義指令來解決

首先在directives.js文件中添加rjCloseBackDrop指令, 用來解決上面第二個問題

.directive('rjCloseBackDrop', [function() {
        return {
            scope: false,//共享父scope
            restrict: 'A',
            replace: false,
            link: function(scope, iElm, iAttrs, controller) {
                //要在html上添加點擊事件, 試了很久- -!
                var htmlEl = angular.element(document.querySelector('html'));
                htmlEl.on("click", function(event) {
                    if (event.target.nodeName === "HTML" &&
                        scope.popup.optionsPopup &&
                        scope.popup.isPopup) {
                        scope.popup.optionsPopup.close();
                        scope.popup.isPopup = false;
                    }
                });
            }
        };
    }])

再創建rjHoldActive指令, 用來解決第一個問題

.directive('rjHoldActive', ['$ionicGesture', '$timeout',
        function($ionicGesture, $timeout, $ionicBackdrop) {
            return {
                scope: false,
                restrict: 'A',
                replace: false,
                link: function(scope, iElm, iAttrs, controller) {
                    $ionicGesture.on("hold", function() {
                        iElm.addClass('active');
                        //300ms后恢復
                        $timeout(function() {
                            iElm.removeClass('active');
                        }, 300);
                    }, iElm);
                }
            };
        }
    ])

最后分別在ion-listion-item上添加指令

<ion-list rj-close-back-drop>
    <ion-item class="item-avatar"rj-hold-active ng-repeat="message in messages">

ok, 問題解決, 有點小激動~

自定義服務

前面講的都是界面的東西, 那聊天記錄的數據哪里來?
這里我們自定義一個假json數據, 用來模擬, 在www目錄下創建文件data/json/messages.json

"messages": [{
        "id": 0,
        "name": "李明",
        "pic": "img/adam.jpg",
        "lastMessage": {
            "time": "2015-10-12 15:34:55",
            "content": "你在干什么?",
            "isFromeMe": false
        },
        "noReadMessages": 2,
        "showHints": true
    },...

目前用到的數據都定義在這, 后面還需要什么數據再添加
我們把數據存到localstorage中, 大家都知道localstorage是基於keyvalue存儲的
總不能把所以人的消息都存在一條key中, 所以我定義兩個服務

  1. 把整個json數據拆成單獨的message, 把獨立的message合並成一個對象
  2. 封裝setItem, 基本數據的存儲獲取

具體我就不貼代碼了, 講下服務定義好了, 怎么使用, 比如定義了一個test服務:

.factory('test', ['', function(){
    return{
        dosomething: function(){
            return 0;
        }
    };
}])

用的時候直接把test注入, test.dosomething()調用:

.controller('someCtrl', function($scope, test) {
    test.dosomething();
    ...
}

是不是很簡單?

最后

這篇寫的很長, 其實實現的功能很簡單, 主要是要學會如何定義樣式, 自定義指令, 自定義服務
這樣在后面實現更復雜的功能時, 不至於糾結這些細節.

我發現一個人自學, 確實有些困難, 一些小問題百度根本搜不到, google上才比較靠譜

所以小伙伴們遇到困難, 不妨google一下, 基本都有答案的哦
有問題歡迎大家評論, 我會的會及時回復~

Git代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM