Angular 入门(三) 手机端开发

上篇总结:

  • 管道 pipe

               相当于vue中的过滤器. 使用时: {{值 | 管道名:参数:参数...}}

               angular默认官方提供了一些常用管道, 可以直接使用

               也提供了自定义的方式: ng g p 管道名

  • 指令 directive

               生成命令: ng g d 指令名, 用于操作元素的 DOM 属性

  • 生命周期

               初始化 ngOnInit -> 挂载时 init -> 更新时 checked -> 销毁 destroy

  • 组件间的参数传递

–            父子: 子中用 @Input() 关键词声明属性即可

–            子父: 子中要声明事件, 向外传递数据 @Output(), 父通过事件方式 传递一个 自身方法 给子, 子触发传入的方法 向方法中传递数据

–            兄弟: 子1 -> 父 -> 子2 或 服务进行全局状态管理.

  • 服务: 同vue 的 Vuex

               生成服务命令: ng g s 服务名

               使用时, 要通过 依赖注入 机制来完成.

–            依赖注入: 在构造函数的参数 中声明类型, 组件在使用时 就必须传递对应的类型的值.

–            其中: 我们负责声明依赖即可; 注入操作由系统自动完成;

               语法糖用法: constructor(权限词 参数名: 服务类型)

  • 网络服务: 官方提供了很多强大的服务, 网络服务是其中一种

–            网络模块默认未加载, 必须到 app.module.ts 文件中加载才可以

 话不多说直入主题 ;接下来介绍手机端的开发

 Ionic_________________

 Vue 有 mintUI, 制作手机端的界面

Angular 有 ionic, 制作手机端的 UI库

脚手架的安装:

npm install -g @ionic/cli --force

生成项目包

ionic start ionicApp blank
//     生成   包名      类型((blank/sidemenu/tabs)
/**
*- blank: 基础包
*- tabs: 带有标签栏导航的包
*- sidemenu: 带有侧边栏导航的包
/

包的运行:

ionic s

vscode插件:

 主要容器:

  • ion-app: 根容器
  • ion-header: 头部导航栏容器
  • ion-content: 主体内容部分
  • ion-footer: 底部容器

 更多组件详细介绍请点这里

 button按钮组件

<!-- 按钮组件 -->
<!-- https://ionicframework.com/docs/api/button -->
<ion-app>
  <ion-header>
    <ion-toolbar>
      <ion-title>按钮</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content>
    <!-- 组件的风格, 默认会自动适配所在操作系统 -->
    <ion-button>我是按钮</ion-button>

    <!-- mode: 指定风格 -->
    <ion-button mode="ios">ios</ion-button>
    <ion-button mode="md">android</ion-button>

    <!-- 官方自带很多主题  theme -->
    <br />
    <ion-button color="primary">primary</ion-button>
    <ion-button color="secondary">secondary</ion-button>
    <ion-button color="tertiary">tertiary</ion-button>
    <ion-button color="success">success</ion-button>
    <ion-button color="warning">warning</ion-button>
    <ion-button color="danger">danger</ion-button>
    <ion-button color="light">light</ion-button>
    <ion-button color="medium">medium</ion-button>
    <ion-button color="dark">dark</ion-button>

    <!-- 大小 -->
    <br />
    <ion-button size="small">small</ion-button>
    <ion-button size="default">default</ion-button>
    <ion-button size="large">large</ion-button>

    <!-- 填充方式 -->
    <br />
    <ion-button fill="outline">outline</ion-button>
    <ion-button fill="solid">solid</ion-button>
    <ion-button fill="clear">clear</ion-button>

    <!-- 扩展方式 -->
    <br />
    <ion-button expand="block">block</ion-button>
    <ion-button expand="full">full</ion-button>

    <!-- 不可用 -->
    <br />
    <ion-button disabled>不可用</ion-button>
  </ion-content>
</ion-app>
View Code

bdge徽章

<!-- 徽章组件 badge -->
<!-- https://ionicframework.com/docs/api/badge -->
<ion-app>
  <ion-header>
    <ion-toolbar>
      <ion-title>badge徽章</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content>
    <ion-badge>42</ion-badge>
    <ion-badge color="success">success</ion-badge>
    <ion-badge mode="ios" color="danger">ios</ion-badge>
  </ion-content>
</ion-app>
View Code

icon图标

<!-- 图标库 -->
<!-- https://ionicons.com/ -->
<ion-app>
  <ion-header>
    <ion-toolbar>
      <ion-title>icon</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content>
    <ion-icon name="add" style="font-size: 30px"></ion-icon>

    <ion-icon name="logo-alipay" style="font-size: 50px" color="secondary"></ion-icon>
    <!-- 可以搭配按钮使用 -->
    <ion-button>
      <ion-icon name="add"></ion-icon>
    </ion-button>
  </ion-content>
</ion-app>
View Code

card卡片组件

<!-- 卡片组件 -->
<!-- https://ionicframework.com/docs/api/card -->
<ion-app>
  <ion-header>
    <ion-toolbar>
      <ion-title>卡片</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content>
    <!-- i-card-full -->
    <ion-card>
      <img src="http://101.96.128.94:9999/mfresh/news_imgs/01.jpg" alt="" />
      <ion-card-header>
        <ion-card-subtitle>此净化器功能优秀, 节能减排, 价格优美.</ion-card-subtitle>
        <ion-card-title>净美仕净化器</ion-card-title>
      </ion-card-header>
      <ion-card-content>
        打掉的的阿达的看了看.马卡龙文件但大家拿健康的宽带连接我已大奖等你
      </ion-card-content>
    </ion-card>
  </ion-content>
</ion-app>
View Code
横向滚动展示
<!-- 横向滚动展示 -->
<!-- https://ionicframework.com/docs/api/slides -->
<ion-app>
  <ion-header>
    <ion-toolbar>
      <ion-title>横向滚动展示</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content>
    <!-- slides: 容器;   slide: 项目 -->

    <!-- pager: 页数指示 -->
    <!-- loop: 循环滚动 -->
    <!-- autoplay: 自动滚动 -->
    <!-- disableOnInteraction: 用户触摸之后 让自动滚动失效;  默认为true -->
    <ion-slides
      pager
      [options]="{ loop: true, autoplay: { disableOnInteraction: false } }"
    >
    <!-- 在ts文件先定义好图片路径的数组 -->
      <ion-slide *ngFor="let item of images">
        <img [src]="item" alt="" />
      </ion-slide>
    </ion-slides>
  </ion-content>
</ion-app>
View Code

 grid栅格

<!-- 栅格布局 -->
<!-- https://ionicframework.com/docs/api/grid -->

<ion-app>
  <ion-header>
    <ion-toolbar>
      <ion-title>栅格布局</ion-title>
    </ion-toolbar>
  </ion-header>
  <ion-content>
    <!-- i-grid -->
    <!-- 在scss中定义样式grid-lianxi -->
    <ion-grid fixed class="grid-lianxi">
      <ion-row>
        <!-- 每行最多12列,  size代表列数 -->
        <ion-col size="6">6</ion-col>
        <ion-col size="6">6</ion-col>
      </ion-row>

      <ion-row>
        <!-- 超出会换行 -->
        <ion-col size="4">4</ion-col>
        <ion-col size="5">5</ion-col>
        <ion-col size="6">6</ion-col>
        <ion-col size="7">7</ion-col>
      </ion-row>

      <ion-row>
        <ion-col size="3">3</ion-col>
        <!-- 不写会自动填充剩余份数 -->
        <ion-col>不写份数</ion-col>
      </ion-row>
    </ion-grid>
  </ion-content>
</ion-app>
View Code

 综合这些组件的一个例子

html:

<!-- 新闻 -->
<ion-app>
  <ion-header>
    <ion-toolbar color="danger">
      <ion-title>网易新闻</ion-title>
    </ion-toolbar>
  </ion-header>

  <!-- scrollEvents: 允许监听滚动事件, 默认false -->
  <!-- ionScroll: 滚动事件 -->
  <ion-content
    *ngIf="news"
    #content
    [scrollEvents]="true"
    (ionScroll)="onScroll($event)"
  >
    <!-- 下拉刷新 -->
    <ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
      <ion-refresher-content></ion-refresher-content>
    </ion-refresher>

    <ion-grid fixed class="news-grid">
      <ion-row>
        <ion-col size="6" *ngFor="let item of news.result">
          <ion-card>
            <img [src]="item.image" alt="" />
            <div class="content">
              <div>{{ item.title }}</div>
              <div>{{ item.passtime }}</div>
            </div>
          </ion-card>
        </ion-col>
      </ion-row>
    </ion-grid>

    <!-- 加载更多 -->
    <!-- threshold: 触底阈值. 10% 代表剩余未显示区域的高度 是 显示区域高度 10% 时触发触底操作 -->
    <ion-infinite-scroll
      threshold="10%"
      position="bottom"
      (ionInfinite)="loadData($event)"
    >
      <ion-infinite-scroll-content
        loadingSpinner="dots"
        loadingText="加载中..."
      >
      </ion-infinite-scroll-content>
    </ion-infinite-scroll>

    <!-- 悬浮按钮: 可以悬浮在已有内容的上方 -->
    <!-- vertical: 竖向, 可选值 top/center/bottom 对应 上/中/下 -->
    <!-- horizontal: 横向, 可选值 start/center/end -->
    <ion-fab
      [hidden]="!showGoTop"
      vertical="bottom"
      horizontal="end"
      slot="fixed"
    >
      <ion-fab-button (click)="goTop()">
        <ion-icon name="arrow-up-outline"></ion-icon>
      </ion-fab-button>
    </ion-fab>
  </ion-content>
</ion-app>
View Code

scss:

.grid-lianxi {
  border: 1px solid red;

  ion-row {
    border: 2px solid orange;

    ion-col {
      border: 1px solid blue;
    }
  }
}

.news-grid {
  padding: 3px;

  img {
    width: 100%;
  }

  ion-col {
    padding: 3px;
  }

  ion-card {
    margin: 0;

    .content {
      padding: 4px;

      div:first-child {
        color: black;
        text-overflow: -o-ellipsis-lastline;
        overflow: hidden;
        text-overflow: ellipsis;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        line-clamp: 2;
        -webkit-box-orient: vertical;
        font-size: 1.1em;
        margin-bottom: 3px;
      }
    }
  }
}
View Code

ts:

import { HttpClient } from '@angular/common/http';
import { Component, ViewChild } from '@angular/core';
import { IonContent } from '@ionic/angular';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  // 掌控子元素, 绑定变量 content 到 ion-content 组件
  @ViewChild('content') content: IonContent;

  showGoTop = false; //是否要显示 回到顶部 按钮

  // 绑定到 ion-conent 的滚动监听事件, 当滚动时自动触发
  onScroll(event) {
    console.log(event);

    const y = event.detail.currentY; //当前竖向滚动的 y
    //如果 y > 1200 就显示回到头部按钮
    this.showGoTop = y > 1200;
  }

  goTop() {
    // scrollToTop(动画时长);  单位毫秒
    this.content.scrollToTop(250);
  }

  constructor(public http: HttpClient) {}

  getUrl(pno: number) {
    return 'https://api.apiopen.top/getWangYiNews?page=' + pno;
  }

  news: News;

  ngOnInit(): void {
    const url = this.getUrl(1);

    this.http.get(url).subscribe((res: News) => {
      console.log(res);

      this.news = res;
    });
  }

  page = 1;

  //下拉刷新
  doRefresh(event) {
    console.log('下拉刷新触发!');
    const url = this.getUrl(1);
    this.http.get(url).subscribe((res: News) => {
      console.log(res);

      this.news = res;
      this.page = 1; //重置为 第一页

      event.target.complete(); //结束下拉刷新动画的显示
    });
  }

  // 触底时触发
  loadData(event) {
    // console.log(event);

    const url = this.getUrl(this.page + 1);

    this.http.get(url).subscribe((res: News) => {
      console.log(res);
      // 合并新旧数据中的数组
      res.result = this.news.result.concat(res.result);

      this.news = res;

      this.page++; //成功后, 页数+1

      //通知组件此次加载操作已完成;   这样组件才会监听下一次
      event.target.complete();
    });
  }

  images = [
    'http://101.96.128.94:9999/mfresh/images/banner_01.jpg',
    'http://101.96.128.94:9999/mfresh/images/banner_02.jpg',
    'http://101.96.128.94:9999/mfresh/images/banner_03.jpg',
    'http://101.96.128.94:9999/mfresh/images/banner_04.jpg',
  ];
}

/////
///// 返回值结构声明
interface News {
  code: number;
  message: string;
  result: NewsResult[];
}

interface NewsResult {
  image: string;
  passtime: string;
  path: string;
  title: string;
}
View Code

 item组件

<!-- item组件 -->
<!-- https://ionicframework.com/docs/api/item -->
<ion-app>
  <ion-header>
    <ion-toolbar>
      <ion-title>item</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content>
    <ion-item>
      <ion-label>Awesome Label</ion-label>
    </ion-item>

    <!-- button: 可以点击 -->
    <!-- detail: 右侧出现 箭头图标 -->
    <ion-item button detail>
      <ion-label>Click me</ion-label>
    </ion-item>

    <ion-item>
      <!-- slot: 插槽;   item具有左右两个插槽, start 和 end -->
      <ion-badge slot="end">42</ion-badge>
      <ion-label>Item Avatar</ion-label>
    </ion-item>

    <ion-item>
      <!-- avatar: 把内部图片变圆形 -->
      <ion-avatar slot="start">
        <img
          src="http://www.gx8899.com/uploads/allimg/2017112908/pc2e3vft403.jpg"
        />
      </ion-avatar>
      <ion-label>
        <h3>重庆天花板</h3>
        <p>今天的面试题超级简单, 妥妥的~</p>
      </ion-label>
      <ion-badge color="danger" slot="end">42</ion-badge>
    </ion-item>

    <ion-item>
      <ion-icon name="settings" slot="start"></ion-icon>
      <ion-label>设置</ion-label>
    </ion-item>

    <ion-item lines="none">
      <ion-label>没有分割线</ion-label>
    </ion-item>

    <ion-item lines="full">
      <ion-label>分割线充满</ion-label>
    </ion-item>

    <ion-item>
      <ion-label>用户名:</ion-label>
      <ion-input placeholder="账号/手机号/邮箱"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label>密码:</ion-label>
      <ion-input placeholder="密码" type="password"></ion-input>
    </ion-item>

    <!-- 分组 -->
    <ion-item-group>
      <ion-item-divider>
        <ion-label>A</ion-label>
      </ion-item-divider>

      <ion-item>
        <ion-label>阿宝</ion-label>
      </ion-item>
      <ion-item>
        <ion-label>阿花</ion-label>
      </ion-item>

      <ion-item-divider>
        <ion-label>B</ion-label>
      </ion-item-divider>

      <ion-item>
        <ion-label>宝蓝</ion-label>
      </ion-item>
      <ion-item>
        <ion-label>boner</ion-label>
      </ion-item>
    </ion-item-group>

    <!-- i-item-sliding: 通过滑动 显示隐藏操作 -->
  </ion-content>
</ion-app>
View Code

例:网络模块+组件+跨域

html:

<ion-app>
  <ion-header>
    <ion-toolbar color="warning">
      <ion-title>直播列表</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content *ngIf="res" #content [scrollEvents]="true" (ionScroll)="onScroll($event)">
    <ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
      <ion-refresher-content></ion-refresher-content>
    </ion-refresher>

    <ion-grid fixed class="douyu-grid">
      <ion-row>
        <ion-col size="6" *ngFor="let item of res.data.list">
          <ion-card>
            <div class="card-header">
              <img [src]="item.roomSrc" alt="" />
              <div class="hn">{{ item.hn }}</div>
              <div class="nick">
                <ion-avatar>
                  <img [src]="item.avatar" />
                </ion-avatar>
                <span>{{ item.nickname }}</span>
              </div>
            </div>
            <div class="room-name">{{ item.roomName }}</div>
          </ion-card>
        </ion-col>
      </ion-row>
    </ion-grid>

    <!-- i-infinite-scroll -->
    <ion-infinite-scroll threshold="10%" position="bottom" (ionInfinite)="loadData($event)">
      <ion-infinite-scroll-content loadingSpinner="bubbles" loadingText="加载中...">
      </ion-infinite-scroll-content>
    </ion-infinite-scroll>

    <!-- 悬浮按钮 -->
    <ion-fab [hidden]="!showGoTop" vertical="bottom" horizontal="end" slot="fixed">
      <ion-fab-button (click)="goTop()">
        <ion-icon name="arrow-up-outline"></ion-icon>
      </ion-fab-button>
    </ion-fab>
  </ion-content>
</ion-app>
View Code

ts:(注意在app.module.ts中引入HttpClientModule模块)

import { HttpClient } from '@angular/common/http';
import { Component, ViewChild } from '@angular/core';
import { IonContent } from '@ionic/angular';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  @ViewChild('content') content: IonContent;

  showGoTop = false;

  onScroll(e) {
    this.showGoTop = e.detail.currentY > 1000;
  }

  goTop() {
    this.content.scrollToTop(200);
  }

  getUrl(page: number) {
    // 请求地址以 /douyu 开头,  代理就会进行解析
    return `/douyu/api/room/list?page=${page}&type=yz`;
  }

  // 依赖注入机制: 声明依赖
  constructor(public http: HttpClient) { }

  res: Douyu;

  // 下拉刷新
  doRefresh(e) {
    const url = this.getUrl(1);

    this.http.get(url).subscribe((res: Douyu) => {
      this.res = res;

      e.target.complete(); //终止下拉刷新动画
    });
  }

  // 加载更多
  loadData(e) {
    const url = this.getUrl(this.res.data.nowPage + 1);

    this.http.get(url).subscribe((res: Douyu) => {
      //合并新旧数据数组,  然后把新的数据 替换旧的
      res.data.list = this.res.data.list.concat(res.data.list);

      this.res = res;

      e.target.complete(); // 声明本次加载更多操作已完成,  准备下一次
    });
  }

  ngOnInit(): void {
    this.http.get(this.getUrl(1)).subscribe((res: Douyu) => {
      console.log(res);
      this.res = res;

      // 默认数据量8条: 不足以充满整个页面, 就会导致没有触底操作
      // 再请求第二页数据 与第一页合并在一起
      this.http.get(this.getUrl(2)).subscribe((res: Douyu) => {
        res.data.list = this.res.data.list.concat(res.data.list);

        this.res = res;
      });
    });
  }
}

/////
///// 返回值的数据结构声明
interface Douyu {
  code: number;
  data: DouyuData;
}

interface DouyuData {
  cate2Id: number;
  list: DouyuDataList[];
  nowPage: number;
  pageCount: number;
}

interface DouyuDataList {
  avatar: string;
  cate1Id: number;
  cate2Id: number;
  hn: string;
  isLive: number;
  isVertical: number;
  liveCity: string;
  nickname: string;
  rid: number;
  roomName: string;
  roomSrc: string;
  verticalSrc: string;
  vipId: number;
}
View Code

scss:

.douyu-grid {
    padding: 3px;
  
    ion-col {
      padding: 3px;
  
      ion-card {
        margin: 0;
  
        img {
          width: 100%;
        }
      }
    }
  }
  
  .card-header {
    position: relative;
  
    .hn {
      position: absolute;
      top: 0;
      right: 0;
      background-color: rgba(0, 0, 0, 0.5);
      color: white;
      padding: 4px;
    }
  
    .nick {
      position: absolute;
      bottom: 0;
      left: 0;
      display: flex;
      background-color: rgba(0, 0, 0, 0.5);
      align-items: center;
      color: white;
      right: 0;
  
      ion-avatar {
        width: 20px;
        height: 20px;
        margin: 3px;
      }
    }
  
    img {
      display: block;
    }
  }
  
  .room-name {
    padding: 4px;
    color: black;
  
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  
View Code

创建src目录下proxy.config.json文件跨域  在angular.json中引入

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

a small tree

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

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

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

打赏作者

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

抵扣说明:

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

余额充值