使用怎么创建小程序的过程

48 阅读4分钟

uni-app小程序

uniapp创建

查看本地安装好的vue版本

vue -V

要求不能是5的版本,要4的版本

image-20220705090126363-16569828877751.png

全局卸载

npm un -g @vue/cli

安装指定版本

npm install -g @vue/cli@4

使用uniapp来创建项目

vue create -p dcloudio/uni-preset-vue hmyg75

填写 appid

在 manifest.json 中填写appid

  "mp-weixin": {
    /* 微信小程序特有相关 */ "appid": "wxad258ddc70c8662c",
    "setting": {
      "urlCheck": false
    },
    "usingComponents": true
  },

运行项目

npm run dev:mp-weixin

image-20220705095141992.png

微信开发者工具导入 编译好的代码

导入这个路径

image-20220705095204297.png

引入 uview

uview 和 uniapp配套的全端UI框架

使用步骤

  1. 安装依赖

    npm i uview-ui@1.8.4 sass 
    
  2. main.js 引入以下配置

    import uView from "uview-ui";
    Vue.use(uView);
    
  3. uni.scss 引入主题样式文件

    @import 'uview-ui/theme.scss';
    
  4. 引入uView基础样式 App.vue

    <style lang="scss">
    	/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
    	@import "uview-ui/index.scss";
    </style>
    
  5. 修改 pages.json

    {
    	"easycom": {
    		"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
    	},
    	
    	// 此为本身已有的内容
    	"pages": [
    		// ......
    	]
    }
    
  6. 拷贝了uview的组件代码

        <u-button>默认按钮</u-button>
        <u-button type="primary">主要按钮</u-button>
        <u-button type="success">成功按钮</u-button>
        <u-button type="info">信息按钮</u-button>
        <u-button type="warning">警告按钮</u-button>
        <u-button type="error">危险按钮</u-button>
    
  7. 成功提示

image-20220705144559476.png

新建4个关键的页面

  1. 分布建立页面文件

image-20220705155006769.png 2. 让页面里面有代码

image-20220705155021170.png

  1. pages.json 添加了 4个页面记录

image-20220705155047325.png

  1. 回到 微信开发者工具中 简单验证了 4个页面创建是成功

image-20220705155112503.png

引入tabbar

image-20220705163106088.png

  1. 拷贝 图标文件到 uniapp项目中

image-20220705161627952.png

  1. 找到配置文件 pages.json 设置tabbar 。 拷贝以下代码到一级层级下即可

      "tabBar": {
        "color": "#666",
        "selectedColor": "#eb4450",
        "borderStyle": "black",
        "backgroundColor": "#ffffff",
        "list": [
          {
            "pagePath": "pages/index/index",
            "iconPath": "static/icons/home.png",
            "selectedIconPath": "static/icons/home-o.png",
            "text": "首页"
          },
          {
            "pagePath": "pages/category/category",
            "iconPath": "static/icons/category.png",
            "selectedIconPath": "static/icons/category-o.png",
            "text": "分类"
          },
          {
            "pagePath": "pages/cart/cart",
            "iconPath": "static/icons/cart.png",
            "selectedIconPath": "static/icons/cart-o.png",
            "text": "购物车"
          },
          {
            "pagePath": "pages/my/my",
            "iconPath": "static/icons/my.png",
            "selectedIconPath": "static/icons/my-o.png",
            "text": "我的"
          }
        ]
      }
    

设置了页面导航栏样式

image-20220705163117225.png

pages.json

  "globalStyle": {
    "navigationBarTextStyle": "white",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#eb4450",
    "backgroundColor": "#F8F8F8"
  },

封装 搜索框组件

借助了uview 搜索框组件 来实现封装

  1. 使用 easycom 模式来创建组件

image-20220705170301134.png

  1. 组件代码

    <template>
      <view class="yg-search">
        <u-search
          placeholder="搜索"
          shape="square"
          :show-action="false"
          input-align="center"
          bg-color="#fff"
        ></u-search>
      </view>
    </template>
    
    <script>
    export default {};
    </script>
    
    <style lang="scss">
    .yg-search {
      background-color: #ea4350;
      padding: 15rpx;
    }
    </style>
    
  2. 回到首页中 直接使用

        <!-- 1 搜索框 -->
        <YgSearch></YgSearch>
    

轮播图

image-20220705173543929.png

  1. 自己发送请求获取数据

    // 获取轮播图
    async getSwiperData() {
      // uni api
      const [err, data] = await uni.request({
        url: "https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata",
      });
      this.swiperList = data.data.message;
    },
    
  2. 然后将数据结合组件 u-swiper 实现功能

    <!-- 2 轮播图 -->
    <!-- 
      name="image_src" 
      因为我们 swiperList 是对象数组 存放图片属性名 image_src name属性来指定即可
    
     -->
    <u-swiper
      :list="swiperList"
      name="image_src"
      height="340"
    ></u-swiper>
    

封装网络请求代码

uview 提供 直接使用即可

实现功能

  1. 后期方便我们统一修改 url
  2. 自动实现 显示加载中

步骤

  1. 新建 请求拦截器文件 src\common\http.interceptor.js

    const install = (Vue, vm) => {
      // 此为自定义配置参数,具体参数见上方说明
      Vue.prototype.$u.http.setConfig({
        // 基地址
        baseUrl: 'https://api-hmugo-web.itheima.net/api/public/v1',
        // 发送请求过程中 提示文字
        loadingText: '努力加载中~',
        // 发送请求的时候 过了800毫秒 才显示加载中
        loadingTime: 800,
      });
    };
    
    export default {
      install,
    };
    
  2. main.js 引入这个文件

const app = new Vue({
  ...App,
});

// http拦截器,此为需要加入的内容,如果不是写在common目录,请自行修改引入路径
import httpInterceptor from '@/common/http.interceptor.js';
// 这里需要写在最后,是为了等Vue创建对象完成,引入"app"对象(也即页面的"this"实例)
Vue.use(httpInterceptor, app);

app.$mount();
  1. 在页面中 发送请求的代码 切成 uview的写法

        async getSwiperData() {
          // uni api =>uview 写法
          const result = await this.$u.get("/home/swiperdata");
          // console.log(result);
          this.swiperList = result.message;
        },
    

商品分类页面布局

<template>
  <view>
    <!-- 1 搜索框 -->
    <YgSearch></YgSearch>
    <!-- 2 内容 -->
    <view class="main">
      <view class="menu"></view>
      <view class="content"></view>
    </view>
  </view>
</template>

<script>
export default {};
</script>

<style lang="scss">
.main {
  height: calc(100vh - 94rpx);
  display: flex;
  .menu {
    width: 182rpx;
    overflow: auto;
  }
  .content {
    flex: 1;
    overflow: auto;
  }
}
</style>

小程序的性能优化建议

image-20220707121114162.png

在uniapp中,如果标签中没有出现的变量,就不要定义的data中,使用的话 一样可以正常 this.abc来使用

小程序页面跳转和传参

使用 navigator 进行跳转和传参

 :url="'/pages/goods_list/goods_list?cid='+item2.cat_id"

在新页面中 onLoad 生命周期 接收 数据

  onLoad(option) {
    // 为了方便调试  cid = 5
    const cid = option.cid || 5;
    console.log(cid);
  },

小程序中滚动条触底事件

developers.weixin.qq.com/miniprogram…

onReachBottom(){}

商品列表页面下拉刷新业务

image-20220708090918228.png

  1. pages.json 开启 允许下拉刷新

          "path": "pages/goods_list/goods_list",
          "style": {
            "navigationBarTitleText": "商品列表",
            "enablePullDownRefresh": true
          }
    
  2. 在页面中 监听 页面下拉刷新事件

    onPullDownRefresh(){}
    
  3. 执行业务

image-20220708091040006.png

  async onPullDownRefresh() {
    this.params.pagenum = 1;
    this.goods = [];
    await this.getGoods(); // 异步   开始发送请求 获取数据 数据还没有回来
    uni.stopPullDownRefresh(); // 关闭下拉刷新
  },

商品详情页面业务分析

  1. 通过接口获取到商品详情数据

  2. 动态页面渲染

  3. 轮播图

image-20220708094049137.png

    <u-swiper
      :list="goodsDetail.pics"
      name="pics_big"
      height="497"
      img-mode="aspectFit"
      bg-color="#fff"
    ></u-swiper>
  1. 点击轮播图 放大预览 wx.previewImage

        // 点击轮播图
        // index 点击 第几张图片 下标
        handlePreviewImage(index) {
          // console.log(index);
          // console.log(this.goodsDetail.pics);
          const urls = this.goodsDetail.pics.map((item) => item.pics_big);
          uni.previewImage({
            // 数组构造即可
            // 需要轮播图图书数组
            urls,
            // 你要先显示谁
            current: urls[index],
          });
        },
    
  2. 商品名称价格

image-20220708094143604.png 6. 图文详情渲染 - 富文本

image-20220708094213098.png

  1. 数据 来自于接口文档

image-20220708114924923.png

  1. 用什么标签来渲染

    1. rich-text 小程序 富文本标签 简单内容 用它

      <rich-text :nodes="goodsDetail.goods_introduce"></rich-text>
      
    2. v-html vue中技术

      <view v-html="goodsDetail.goods_introduce"></view>
      
    3. uviewParse 组件 文章内容 图文详情 复杂结构

      <u-parse :html="goodsDetail.goods_introduce"></u-parse>
      
  2. 渲染购物车工具栏 - uview 模版

image-20220708094235266.png

  1. 注册一个uniapp账号

  2. 然后打开在 uview 模版中寻找模版

image-20220708120742023.png 3. 然后打开链接

image-20220708120758716.png

  1. 下载使用

image-20220708120828815.png

  1. 然后按需拷贝要的代码结构到自己的项目中

在uniapp中引入vuex

看 uniapp中文档来操作

  1. 购物车数据需要在多个页面中使用 (商品详情页面购物车页面支付页面

  2. 安装依赖, uniapp 已经提前帮我们安装好

  3. 新建 src/store/index.js

    // 页面路径:store/index.js
    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex); //vue的插件机制
    
    //Vuex.Store 构造器选项
    const store = new Vuex.Store({
      state: {
        //存放状态
        username: 'foo',
        age: 18,
      },
    });
    export default store;
    
    
  4. main.js 来全局引入

    import store from './store';
    
    Vue.prototype.$store = store;
    
    const app = new Vue({
      store,
      ...App,
    });
    
  5. 在组件中 通过 计算属性来使用

      computed: {
        username() {
          return this.$store.state.username;
        },
      },
    

    <view class="buy btn u-line-1">立即购买 {{username}} </view>
    
  6. 成功

image-20220708150705844.png

在vuex中划分购物车模块

  1. store/modules/cart.js

    export default {
      state: {
        // 数组
        goodsList: [],
      },
      getters: {},
      mutations: {},
      actions: {},
    };
    
  2. store/index.js 引入 购物车模块

    // 引入 购物车模块
    import cart from '@/store/modules/cart';
    
    const store = new Vuex.Store({
      state: {},
      // 子模块
      modules: {
        cart,
      },
    });
    
  3. 在组件中使用

    this.$store.state.cart.goodsList
    

添加商品到购物车

  1. 引入 vuex 辅助函数 mapMutations

    import { mapMutations } from "vuex";
    
  2. 在组件中 methods 使用了辅助函数 快速获取到mutation中的函数

    写法参考官网

image-20220708160411057.png

...mapMutations("cart", ["cartAddGoods"]),
  1. 在组件中 绑定点击事件

    <view
      class="cart btn u-line-1"
      @click="handleAddCart"
    >加入购物车</view>
    
  2. 事件中开始调用 mutations

     // 加入购物车
        handleAddCart() {
          // console.log(this.goodsDetail);
          // 需要自己添加两个属性 选中状态 和 购买的数量
          this.cartAddGoods({ ...this.goodsDetail, checked: true, nums: 1 });
        },
    
  3. 回到 cart模块 中 mutation 来处理业务

    记得添加 namespaced 属性

      mutations: {
        // 添加数据到购物车数组
        cartAddGoods(state, payload) {
          // 业务后续修改
          state.goodsList.push(payload);
          console.log(state.goodsList);
        },
    

把购物车总数量映射到组件上

  1. 修改了 mutations中 添加商品到购物车逻辑

          const index = state.goodsList.findIndex(
            (goods) => goods.goods_id === payload.goods_id
          );
    
          if (index !== -1) {
            // 已经存在  index
            state.goodsList[index].nums++;
          } else {
            // 不存在
            state.goodsList.push(payload);
          }
    
  2. 把购买的商品总的数量 在 vuex 中cart中计算出来 getters

      getters: {
        // 总商品的购买数量
        goodsTotalNums(state) {
          // 数组方法 reduce
          return state.goodsList.reduce((s, i) => (s += i.nums), 0);
        },
      },
    

    补充数组方法 reduce 叠加器 数量的叠加 字符串叠加

    数量叠加

          const list = [1, 2, 3, 4, 5];
          // const sum = list.reduce(回调函数,初始值);
          // const sum = list.reduce((总和,当前遍历元素)=>{
          //   总和+=当前遍历元素
          //   返回 总和
          // },0);
          // const sum = list.reduce((s, i) => {
          //   console.log('总和 s', s, '当前循环项 i', i);
          //   s += i;
          //   return s;
          // }, 0);
    
          const sum = list.reduce((s, i) => (s += i), 0);
          console.log(sum);
    

    字符串叠加

          const list = ['a', 'b', 'c', 'd'];
          const html = list.reduce((h, i) => (h += `<li>${i}</li>`), '');
          console.log(html);
    
  3. 在组件中使用了getters

    import { mapMutations, mapGetters } from "vuex";
    
      computed: {
        ...mapGetters("cart", ["goodsTotalNums"]),
      },
          
     <view class="item car">
              <u-badge
                :count="goodsTotalNums"
              ></u-badge>
    

购物车页面静态结构

<template>
  <view class="cart">
    <!-- 1 列表 -->
    <view class="cart-list">
      <view class="cart-item">
        <!-- 1 复选框 -->
        <view class="goods-chk">
          <u-checkbox
            value=""
            shape="circle"
            active-color="red"
          ></u-checkbox>
        </view>
        <!-- 2 图片 -->
        <view class="goods-img">
          <u-image
            width="191rpx"
            height="191rpx"
          ></u-image>
        </view>
        <!-- 3 信息 -->
        <view class="goods-info">
          <!-- 名称 -->
          <view class="goods-name u-line-2"></view>
          <!-- 价格和数量 -->
          <view class="goods-price-num">
            <view class="goods-price">¥xxx</view>
            <view class="goods-num-tool">
              <view class="num-btn">-</view>
              <view class="goods-num">xxx</view>
              <view class="num-btn">+</view>
            </view>
          </view>
        </view>
      </view>
    </view>
    <!-- 2 统计 -->
    <view class="statistics">
      <view class="all-chk">
        <u-checkbox
          shape="circle"
          active-color="red"
        >全选</u-checkbox>
      </view>
      <view class="all-price"> 合计: <text>¥xxx</text> </view>
      <view class="all-count">
        <u-button
          type="error"
          shape="circle"
        >去结算(xxx)</u-button>
      </view>
    </view>
  </view>
</template>

<script>
export default {};
</script>

<style lang="scss">
.cart {
  padding-bottom: 111rpx;
  .cart-list {
    .cart-item {
      display: flex;
      padding: 10rpx;
      border-bottom: 1rpx solid #ccc;
      .goods-chk {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .goods-img {
        flex: 2;

        display: flex;
        align-items: center;
        justify-content: center;
      }

      .goods-info {
        color: #666;
        flex: 3;
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        .goods-name {
        }

        .goods-price-num {
          display: flex;
          justify-content: space-between;
          .goods-price {
            color: #eb4450;
          }

          .goods-num-tool {
            width: 140rpx;
            height: 40rpx;

            display: flex;
            justify-content: space-between;
            .num-btn {
              border: 1rpx solid #ccc;
              border-radius: 50%;
              width: 40rpx;
              height: 40rpx;
              text-align: center;
              line-height: 40rpx;
            }
          }
        }
      }
    }
  }
  .statistics {
    position: fixed;
    background-color: #fff;
    bottom: 0;
    left: 0;
    width: 100%;
    z-index: 100;
    border-top: 1rpx solid #ccc;
    display: flex;
    align-items: center;
    padding: 15rpx;
    .all-chk {
    }

    .all-price {
      flex: 1;
      color: #666;
      text {
      }
    }

    .all-count {
    }
  }
}
</style>

支付页面静态结构

<template>
  <view class="pay">
    <!-- 1 收货地址 -->
    <view class="address u-p-20">
      <view class="address-btn u-flex u-row-center">
        <u-button
          shape="circle"
          type="error"
          plain
          size="medium"
          :custom-style="{ backgroundColor: '#fff!important' }"
        >获取收货地址</u-button>
      </view>

      <view class="address-detail">
        <view class="address-detail">xxx</view>
        <view class="address-user">xxx</view>
      </view>
    </view>

    <u-line color="#eee"></u-line>

    <!-- 2 已选商品 -->
    <view class="goods-list u-p-15">
      <view class="goods-list-title">已选商品</view>
      <view class="goods-list-content">
        <view class="cart-item">
          <!-- 2 图片 -->
          <view class="goods-img">
            <u-image
              width="191rpx"
              height="191rpx"
            ></u-image>
          </view>
          <!-- 3 信息 -->
          <view class="goods-info">
            <!-- 名称 -->
            <view class="goods-name u-line-2">xxx</view>
            <!-- 价格和数量 -->
            <view class="goods-price-num">
              <view class="goods-price">¥xxx</view>
              <view class="goods-num-tool">
                <view class="goods-vnum">Xxxx</view>
              </view>
            </view>
          </view>
        </view>
      </view>
    </view>

    <!-- 2 统计 -->
    <view class="statistics">
      <view class="all-price"> 合计: <text>¥xxx</text> </view>
      <view class="all-count">
        <u-button
          type="error"
          shape="circle"
        >去支付(xxx)</u-button>
      </view>
    </view>
  </view>
</template>

<script>
export default {};
</script>

<style lang="scss">
.pay {
  padding-bottom: 111rpx;
}
.cart-item {
  display: flex;
  padding: 10rpx;
  border-bottom: 1rpx solid #ccc;

  .goods-img {
    flex: 2;

    display: flex;
    align-items: center;
    justify-content: center;
  }

  .goods-info {
    color: #666;
    flex: 3;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    .goods-name {
    }

    .goods-price-num {
      display: flex;
      justify-content: space-between;
      .goods-price {
        color: #eb4450;
      }

      .goods-num-tool {
        width: 140rpx;
        height: 40rpx;

        display: flex;
        justify-content: flex-end;

        .goods-vnum {
        }
      }
    }
  }
}
.statistics {
  position: fixed;
  background-color: #fff;
  bottom: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  border-top: 1rpx solid #ccc;
  display: flex;
  align-items: center;
  padding: 15rpx;
  .all-price {
    flex: 1;
    color: #666;
    text {
    }
  }

  .all-count {
  }
}
</style>