• 项目实战【vue,react,微信小程序】(1706C)


    目录

    一、接口封装

    二、vue图片懒加载

    三、书城后端接口

    四、登录、注册、修改密码后端接口

    五、时间戳转日期

    六、文件上传单个文件

     七、上传多个文件

    八、设置淘宝镜像

    九、yarn和npm清缓存

    十、react图片懒加载

    十一、yarn

    十二、react路由懒加载

    十三、让所有接口延时返回

    十四、前端使用代理解决跨域问题

    十五、mock很多数据、分页查找

    十六、如何上线

    十七、小程序轮播图

    十八、父子组件通讯

    十九、路由

    二十、tabBar

    二十一、组件生命周期

    二十二、计算属性

    二十三、小程序购车

    二十四、使用 Component 构造器构造页面

    二十五、使用组件observers做数据监听器

    github源码:


    一、接口封装

    index.js:

    import axios from 'axios'
    import urls from './urls'
    
    console.log(process)
    if (process.env.NODE_ENV === 'development') {
      console.log('env', process.env.NODE_ENV)
      axios.defaults.baseURL = 'http://localhost'
    }
    
    
    axios.interceptors.request.use((config) => {
      return config
    })
    
    axios.interceptors.response.use((res) => {
      if (res.data.code === 400) {
        alert(res.data.message)
      }
      return res
    })
    
    const common = async (config) => {
      let response = await axios(config)
      return response.data
    }
    
    export default {
      login: (data) => common({ url: urls.login, data, method: 'post' }),
      getNav: () => common({ url: urls.getNav }),
      getList: (url) => common({ url: urls.getList + url }),
      updateMyBook: (data) => common({ url: urls.updateMyBook, data, method: 'post' }),
      add:(data) => common({ url: urls.add, data, method: 'post' }),
      getMyBook: () => common({ url: urls.getMyBook }),
      getDetail: (url) => common({ url: urls.getDetail + url })
    }

    urls.js:

    const urls = {
      login: '/api/login',
      getNav: '/api/nav',
      getList: '/api/list',
      updateMyBook: '/api/update_my_book',
      add: '/api/add',
      getMyBook: '/api/get_my_book',
      getDetail: '/api/detail'
    }
    
    export default urls

    拦截器参考链接:http://www.axios-js.com/zh-cn/docs/#%E6%8B%A6%E6%88%AA%E5%99%A8

    二、vue图片懒加载

    参考链接:https://www.npmjs.com/package/vue-lazyload

    注册:

    import Vue from 'vue'
    import VueLazyload from 'vue-lazyload'
    import loadingImg from './images/loading.gif'
    
    Vue.use(VueLazyload, {
      preLoad: 1.3,
      error: loadingImg,
      loading: loadingImg,
      attempt: 1
    })
    
    new Vue({
      render: h => h(App)
    }).$mount('#app')
    

     v-lazy:

          <div class="m-list-item-img-wrap">
            <img v-lazy="item.avatar" alt="" class="m-list-item-img">
          </div>

    样式:

    .m-list-item-img-wrap{display: flex;  112px;height: 150px;background: #dddddd;}
    .m-list-item-img{ 100%;}
    .m-list-item-img[lazy=loading]{margin: auto;  40px;height: 40px;}

    三、书城后端接口

    const express = require('express')
    const { bookNavData, bookMallData, bookMallDetailData } = require('./data')
    const bodyParser = require('body-parser')
    const cors = require('cors')
    const history = require('connect-history-api-fallback')
    
    const app = express()
    
    //用户列表
    let userList = [{
      id: '001',
      username: 'admin',
      password: '123456'
    }, {
      id: '002',
      username: 'xu',
      password: '123'
    }, {
      id: '003',
      username: 'a',
      password: '123456'
    }]
    
    //书包
    let myBook = []
    
    //跨域
    app.use(cors())
    //解析post请求
    
    // parse application/json
    app.use(bodyParser.json())
    app.use(history())
    
    // parse application/x-www-form-urlencoded
    //app.use(bodyParser.urlencoded({ extended: false }))
    
    //静态web服务器
    app.use(express.static( __dirname + '/public'))
     
    //登录
    app.post('/api/login', (req, res) => {
      let { username, password } = req.body
      console.log(JSON.stringify(req.body))
      console.log(username, password)
      let user = userList.find(item => item.username === username)
      if (user) {
        if (user.password === password) {
          res.send({
            code: 200,
            data: {
              username
            },
            message: '登录成功'
          })
        } else {
          res.send({
            code: 400,
            message: '密码错误'
          })
        }
      } else {
        res.send({
          code: 400,
          message: '用户名不存在'
        })
      }
    
    })
    
    //导航
    app.get('/api/nav', (req, res) => {
      res.send({
        code: 200,
        data: bookNavData,
        message: '导航'
      })
    })
    
    //列表
    app.get('/api/list', (req, res) => {
      let { id } = req.query
      let list = bookMallData.find(item => item.id == id).list
      list.forEach(item => {
        item.is_in_my_book = myBook.findIndex(book => book.id === item.id) >= 0
      })
      res.send({
        code: 200,
        data: list,
        message: '列表'
      })
    })
    
    //详情
    app.get('/api/detail', (req, res) => {
      let { id } = req.query
      let detail 
      bookMallDetailData.forEach(item => {
        item.list.forEach(book => {
          if (book.id == id) {
            book.is_in_my_book = myBook.findIndex(item => item.id === book.id) >= 0
            detail = book
          }
        })
      })
    
      res.send({
        code: 200,
        data: detail,
        message: '详情'
      })
    })
    
    //更新书包
    app.post('/api/update_my_book', (req, res) => {
      let { myBookNew } = req.body
      myBook = myBookNew
      res.send({
        code: 200,
        data: myBook,
        message: '更新成功'
      })
    })
    
    //添加
    app.post('/api/add', (req, res) => {
      let { book } = req.body
      myBook.push(book)
      res.send({
        code: 200,
        data: myBook,
        message: '添加成功'
      }) 
    })
    
    //获取书包
    app.get('/api/get_my_book', (req, res) => {
      res.send({
        code: 200,
        data: myBook,
        message: '书包'
      })
    })
    
    app.listen(80)
    console.log(80)

    四、登录、注册、修改密码后端接口

    const express = require('express')
    const bodyParser = require('body-parser')
    const cors = require('cors')
    const history = require('connect-history-api-fallback')
    const uuidv1 = require('uuid/v1')
    const jwt = require('jwt-simple')
    const redis = require('redis')
    
    //用户列表
    let userList = [{
      id: '001',
      username: 'admin',
      password: '123456'
    }, {
      id: '002',
      username: 'xu',
      password: '123'
    }, {
      id: '003',
      username: 'a',
      password: '123456'
    }]
    
    //token加密密码
    let secret = 'xxx'
    
    const app = express()
    
    const client = redis.createClient()
    client.on('error', err => {
      console.log('redis错误:' + err)
    })
    
    //跨域
    app.use(cors())
    //解析post请求
    
    // parse application/json
    app.use(bodyParser.json())
    //let jsonParser = bodyParser.json()
    
    //处理react前端路由(BrowserRoute),vue前端路由(mode:history),注意:开启后无法用postman和浏览器地址栏调试get接口
    //app.use(history())
    
    //静态web服务器
    app.use(express.static(__dirname + '/public'))
    
    //通过中间件检查登录是否过期,并自动续期
    const checkTokenByMiddleware = (req, res, next) => {
      let token = req.headers.token
      client.get(token, (err, response) => {
        if (response) {
          client.set(token, token, 'EX', 60)
          next()
        } else {
          res.send({
            code: 403,
            message: '登录过期'
          })
        }
      })
      console.log(2)
    }
    
    //登录
    app.post('/api/login', (req, res) => {
      let { username, password } = req.body
      let user = userList.find(item => item.username === username)
      if (user) {
        if (user.password === password) {
          let token = jwt.encode(user.id, secret)
          client.set(token, token, 'EX', 60)
          res.send({
            code: 200,
            data: {
              username,
              token
            },
            message: '登录成功'
          })
        } else {
          res.send({
            code: 400,
            message: '密码错误'
          })
        }
      } else {
        res.send({
          code: 400,
          message: '用户名不存在'
        })
      }
    })
    
    //注册
    app.post('/api/register', (req, res) => {
      let { username, password } = req.body
      console.log(username, password)
      let user = userList.find(item => item.username === username)
      if (user) {
        res.send({
          code: 400,
          message: '用户名已存在'
        })
      } else {
        let id = uuidv1()
        userList.push({
          id,
          username,
          password,
        })
        let token = jwt.encode(id, secret)
        client.set(token, token, 'EX', 60)
        res.send({
          code: 200,
          data: {
            userList,
            token
          },
          message: '注册成功'
        })
      }
    })
    
    //修改密码
    app.post('/api/modify_password', checkTokenByMiddleware, async (req, res) => {
      let token = req.headers.token
      let { password } = req.body
      let id = jwt.decode(token, secret)
      console.log(id)
      let index = userList.findIndex(item => item.id === id)
      userList[index].password = password
      res.send({
        code: 200,
        data: userList,
        message: '修改成功'
      })
    })
    
    //动态路由
    app.get('/api/test/:id', (req, res) => {
      let { id } = req.params
      res.send({
        code: 200,
        data: id,
        message: '动态路由测试'
      })
    })
    
    app.listen(82)
    console.log(82)

    五、时间戳转日期

    参考链接:http://momentjs.cn/

    import moment from "moment"
    moment.locale('zh-cn')     
    
    console.log(moment(1573042782076).format('YYYY年MM月DD日 hh:mm:ss'))
    console.log(moment(1573042782076).fromNow())

    六、文件上传单个文件

    controller/upload.js:

    const multer = require('multer')
    
    const storage = multer.diskStorage({
      destination: (req ,file, cb) => {
        cb(null, 'upload')
      },
      filename: (req, file, cb) => {
        cb(null, `${Date.now()} - ${file.originalname}` )
      }
    })
    
    const upload = multer({ storage })
    
    const uploadImg = (req, res) => {
      res.send({
        code: 200,
        data: req.file,
        message: '上传成功'
      })
    }
    
    module.exports = {
      upload,
      uploadImg
    }

    router/upload.js:

    const express = require('express')
    const router = express.Router()
    const { upload, uploadImg } = require('../controller/upload')
    
    router.post('/upload', upload.single('img'), uploadImg)
    
    module.exports = router

    app.js:

    const express = require('express')
    const bodyParser = require('body-parser')
    const cors = require('cors')
    const history = require('connect-history-api-fallback')
    const upload = require('./router/upload')
    
    const app = express()
    
    //跨域
    app.use(cors())
    //解析post请求
    
    // parse application/json
    app.use(bodyParser.json())
    //let jsonParser = bodyParser.json()
    
    //处理react前端路由(BrowserRoute),vue前端路由(mode:history),注意:开启后无法用postman和浏览器地址栏调试get接口
    app.use(history())
    
    //静态web服务器
    app.use(express.static(__dirname + '/public'))
    app.use(express.static(__dirname + '/upload'))
    
    //上传文件
    app.use('/api/', upload)
    
    app.listen(82)
    console.log(82)

    使用postman测试上传接口:

    前端:

    <input type="file" @change="handleUpload" >
    
        handleUpload(e) {
          const data = new FormData()
    
          data.append('img', e.target.files[0])
    
          axios({
            url: '/api/upload',
            data,
            method: 'post',
            timeout: 1000 * 60
          }).then(res => {
            if (res.code === 200) {
    
            }
          })
        }

     七、上传多个文件

    controller/upload.js:

    const multer = require('multer')
    
    const storage = multer.diskStorage({
      destination: (req ,file, cb) => {
        cb(null, 'upload')
      },
      filename: (req, file, cb) => {
        cb(null, `${Date.now()}-${file.originalname}` )
      }
    })
    
    const upload = multer({ storage })
    
    const uploadImg = (req, res) => {
      res.send({
        code: 200,
        data: req.files,   //单个文件:req.file 多个文件:req.files
        message: '上传成功'
      })
    }
    
    module.exports = {
      upload,
      uploadImg
    }

    router/upload.js:

    const express = require('express')
    const router = express.Router()
    const { upload, uploadImg } = require('../controller/upload')
    
    //上传单个文件
    //router.post('/upload', upload.single('img'), uploadImg)
    
    router.post('/upload', upload.array('img', 9), uploadImg)
    
    module.exports = router
    

    app.js和上传单个文件相同

    使用postman测试上传多个文件:

    前端代码:

    <input type="file" multiple="multiple" @change="handleUpload" >
    
    
        handleUpload(e) {
          const data = new FormData()
          let files = e.target.files
          files.forEach(item => {
            data.append('img', item)
          })
          axios({
            url: '/api/upload',
            data,
            method: 'post',
            timeout: 1000 * 60
          }).then(res => {
            if (res.code === 200) {
    
            }
          })
        }
      },

    八、设置淘宝镜像

    yarn config set registry http://registry.npm.taobao.org/
    
    yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass

    九、yarn和npm清缓存

    npm cache clean --force
    
    yarn cache clean

    十、react图片懒加载

    参考链接:

    https://www.npmjs.com/package/react-lazy-load

    import LazyLoad from 'react-lazy-load'
    
          <div key={item.id} className="m-list-item">
            <LazyLoad className="m-list-item-img-wrap">
              <img src={item.avatar} className="m-list-item-img"></img>
            </LazyLoad>
            <div className="m-list-item-info">
              {item.title}
            </div>
          </div>
    .m-list-item{display: flex;margin: 5px;}
    .m-list-item-img-wrap{display: flex;  112px;height: 150px;background: #dddddd;}
    .m-list-item-img-wrap::before{content: '';margin: auto; 38px;height: 38px;background-image: url(./images/loading.png);animation: loading 0.5s linear infinite;}
    .m-list-item-img{position: absolute;  112px;height: 150px;}
    .m-list-item-info{flex:1}
    
    @keyframes loading {
      from {transform: rotate(0deg);}
      to{transform: rotate(360deg);}
    }

    十一、yarn

    yarn是什么? 能干什么?
    yarn是facebook发布的一种包管理工具,作用同npm 一样,是一个包管理用具

    优点:

    快速: 1.会缓存它下载的每个包, 无需重复下载;能并行化操作以最大资源利用率

    可靠: 使用格式详尽而又简洁的 lockfile文件 和确定性算法来安装依赖,能够保证在一个系统上的运行的安装过程也会以同样的方式运行在其他系统上。

    安全: 安装包被执行前校验其完整性

    十二、react路由懒加载

    参考链接:

    https://zh-hans.reactjs.org/docs/code-splitting.html#reactlazy

    import React, { Component, Suspense, lazy } from 'react'
    import { NavLink, Switch, Route } from 'react-router-dom'
    import Home from './Home'
    //import MyBook from './MyBook'
    import Loading from '../components/Loading'
    const MyBook = lazy(async () => { 
      return await new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(import('./MyBook'))
        }, 2000)
      })
    })
    
    export default class Index extends Component {
      render() {
        return (
          <div>
            <div>
              <NavLink to="/index/home" className="m-nav-item">首页</NavLink>
              <NavLink to="/index/my_book" className="m-nav-item">书包</NavLink>
            </div>
            <Suspense fallback={<Loading lazyLoading={true}></Loading>}>
              <Switch>
                <Route path="/index/home" component={Home}></Route>
                <Route path="/index/my_book" component={MyBook}></Route>
              </Switch>
            </Suspense>
          </div>
        )
      }
    }
    

    Loading.js:

    import React, { Component } from 'react'
    import { connect } from 'react-redux'
    
    class Loading extends Component {
      render() {
        let { loading, lazyLoading } = this.props
        return (
          <div className={"m-loading-wrap " + (loading ? 'active ' : '') + (lazyLoading ? 'active' : '')}>
            <span className="m-loading-img"></span>
          </div>
        )
      }
    }
    
    const mapStateToProps = (state) => {
      state = state.toJS()
      return {
        loading: state.loading
      }
    }
    
    export default connect(mapStateToProps)(Loading)
    

    loading样式文件:

    .m-loading-wrap{position: fixed;display: none; top: 0;left: 0;right: 0;bottom: 0; background: rgba(0, 0, 0, 0.5);z-index: 999;}
    .m-loading-wrap.active{display: flex;}
    .m-loading-img{ display: inline-block;margin: auto;  38px;height: 38px;background-image: url(./images/loading.png);background-size: 100% 100%; animation: loading 0.5s linear infinite; }
    
    @keyframes loading {
      from {transform: rotate(0deg);}
      to{transform: rotate(360deg);}
    }

    路由懒加载时,需要懒加载的路由组件特别小,这时很难观察到加载的loading效果,怎么办呢?

    可以把使用Promise模拟延时:

    const MyBook = lazy(async () => { 
      return await new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(import('./MyBook'))
        }, 2000)
      })
    })

    十三、让所有接口延时返回

    目的是测试前端loading效果

    //让所有接口延时返回
    app.use((req, res, next) => {
      setTimeout(() => {
        next()
      }, 500)
    })

    十四、前端使用代理解决跨域问题

    To tell the development server to proxy any unknown requests to your API server in development, add a proxy field to your package.json, for example:

    "proxy": "http://localhost:83"

    也可以增加一个文件:

    装包:

    yarn add http-proxy-middleware

     在src目录下面建一个文件,文件名是setupProxy.js  即 src/setupProxy.js:

    const proxy = require('http-proxy-middleware');
    module.exports = function(app) {
      app.use(
        '/api',
        proxy({
          target: 'http://localhost:83',
          changeOrigin: true,
        })
      );
    };

    参考链接:

    https://create-react-app.dev/docs/proxying-api-requests-in-development/

    十五、mock很多数据、分页查找

    装包:

    yarn add mockjs
    const Mock = require('mockjs')
    
    
    const mockDataList = Mock.mock({
    	'list|100': [{
    		'id|+1': 1,
    		'name': '@cname',
    		'title': '@ctitle',
    		'image': '@image(300x300)',
    		'address': '@county(true)'
    	}]
    }).list
    //分页
    app.get('/api/mock_data', (req, res) => {
      let { page, size } = req.query
      let start = (page - 1) * size
      let end = start + Number(size)
      console.log(start, end)
      let data = mockDataList.slice(start, end)
    
      res.send({
        code: 200,
        data: data,
        message: '列表'
      })
    })

    前端分页,滚动到底加载更多:

    import React, { Component } from 'react'
    import axios from 'axios'
    
    let updateDone = true
    export default class App extends Component {
      constructor(props) {
        super(props)
        this.state = {
          list: [],
          end: '',
          page: 1
        }
      }
      handleScroll(e) {
        let { list, end, page} = this.state
        if (
          e.target.clientHeight + e.target.scrollTop + 200 >
            e.target.scrollHeight &&
          end === "" && updateDone
        ) {
          updateDone = false
          page = page + 1;
          axios({
            url: `/api/mock_data?page=${page}&size=20`
          }).then(res => {
            if (res.data.code === 200) {
              this.setState({
                list: list.concat(res.data.data),
                page
              })
              if (res.data.data.length < 20) {
                console.log("到底了");
                this.setState({
                  end: "到底了"
                })
              }
            }
          });
        }
      }
      componentDidUpdate() {
        updateDone = true
      }
      componentDidMount() {
        axios({
          url: '/api/mock_data?page=1&size=20'
        }).then(res => {
          if (res.data.code === 200) {
            this.setState({
              list: res.data.data
            })
          }
        })
      }
      render() {
        let { list, end } = this.state
        let listDom = list.map(item => (
          <div key={item.id} className="m-list-item">{item.name}</div>
        ))
    
        return (
          <div className="m-warp" onScroll={this.handleScroll.bind(this)}>
            {listDom}
            <div className="m-end">{end}</div>
          </div>
        )
      }
    }
    

    十六、如何上线

    打包:

    yarn build

    利用 Express 托管静态文件:

    //静态web服务器
    app.use(express.static(__dirname + '/public'))
    app.use(express.static('public'))

    参考链接:

    http://www.expressjs.com.cn/starter/static-files.html

    利用 connect-history-api-fallback 解决前端history路由刷新报错:

    const history = require('connect-history-api-fallback')
    
    //处理react前端路由(BrowserRoute),vue前端路由(mode:history),注意:开启后无法用postman和浏览器地址栏调试get接口
    app.use(history())
    

    参考链接:

    https://www.npmjs.com/package/connect-history-api-fallback

    十七、小程序轮播图

      //图片的宽高比等于手机屏幕的宽度和swiper的高度比
      handleImageLoad(e) {
        let { windowWidth } = wx.getSystemInfoSync()
        let { height, width } = e.detail
        height = height /  width * windowWidth
        this.setData({
          height
        })
      },
      <swiper 
        indicator-dots="{{true}}"
        autoplay="{{true}}"
        interval="{{5000}}"
        circular="{{true}}"
        style="height:{{height}}px">
        <swiper-item wx:for="{{banner}}" wx:key="{{index}}">
          <image src="{{item}}" mode="widthFix" class="m-item-img" bindload="handleImageLoad"></image>
        </swiper-item>
      </swiper>

    十八、父子组件通讯

    父组件:

    <book-nav navList="{{navList}}" currentId="{{currentId}}" bind:onNav="handleNav"></book-nav>
      handleNav(e) {
        let { id } = e.detail
        this.setData({
          currentId: id
        })
        wx.request({
          url: `${host}/api/list?id=${id}`,
          success: (res) => {
            if (res.data.code === 200) {
              this.setData({
                currentList: res.data.data
              })
            }
          }
        })
      },

    子组件:

    // components/book-nav/book-nav.js
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
        navList: Array,
        currentId: Number
      },
    
      /**
       * 组件的初始数据
       */
      data: {
    
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
        handleNav(e) {
          let { id } = e.mark
          this.triggerEvent('onNav', { id })
        }
      }
    })
    

    十九、路由

          wx.navigateTo({
            url: `/pages/detail/detail?id=${id}`,
          })
      onLoad: function (options) {
        let { id } = options
        wx.request({
          url: `${host}/api/detail?id=${id}`,
          success: (res) => {
            if (res.data.code === 200) {
              this.setData({
                detail: res.data.data
              })
            }
          }
        })
      },

    二十、tabBar

      "tabBar": {
        "color": "#333333",
        "selectedColor": "#ff0000",
        "list": [
          {
            "pagePath": "pages/home/home",
            "text": "首页",
            "iconPath": "/static/images/home.png",
            "selectedIconPath": "/static/images/home-active.png"
          },
          {
            "pagePath": "pages/my-book/my-book",
            "text": "书包",
            "iconPath": "/static/images/cart.png",
            "selectedIconPath": "/static/images/cart-active.png"
          },
          {
            "pagePath": "pages/index/index",
            "text": "我的",
            "iconPath": "/static/images/me.png",
            "selectedIconPath": "/static/images/me-active.png"
          }
        ]
      }

    二十一、组件生命周期

      lifetimes: {
        ready() {
          wx.request({
            url: `${host}/api/my_book`,
          })
        }
      }
      pageLifetimes: {
        show() {
          wx.request({
            url: `${host}/api/my_book`,
            success: (res) => {
              if (res.data.code === 200) {
                this.setData({
                  myBook: res.data.data
                })
              }
            }
          })
        }
      }

    二十二、计算属性

    在终端进入小程序目录,使用下面的命令省事package.json文件

    npm init -y

    装包:

    yarn add miniprogram-computed

    构建npm:

    构建后生成miniprogram_npm:

    使用计算属性计算总价,总数:

    // pages/my-book/my-book.js
    const computedBehavior = require('miniprogram-computed')
    const { host } = getApp().globalData
    
    Component({
      behaviors: [computedBehavior],
      /**
       * 组件的属性列表
       */
      properties: {
    
      },
    
      /**
       * 组件的初始数据
       */
      data: {
        myBook: []
      },
    
      computed: {
        total(data) {
          let totalPrice = 0, totalCount = 0
          data.myBook.forEach(item => {
            totalCount += item.count
            totalPrice += item.count * item.price
          })
          return {
            totalCount,
            totalPrice
          }
        }
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
    
      },
    
      pageLifetimes: {
        show() {
          wx.request({
            url: `${host}/api/my_book`,
            success: (res) => {
              if (res.data.code === 200) {
                this.setData({
                  myBook: res.data.data
                })
              }
            }
          })
        }
      }
    })
    

    参考链接:

    https://github.com/wechat-miniprogram/computed

    https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html

    二十三、小程序购车

    二十四、使用 Component 构造器构造页面

    页面的生命周期方法(即 on 开头的方法),应写在 methods 定义段中。

    Component({
    
      properties: {
        paramA: Number,
        paramB: String,
      },
    
      methods: {
        onLoad: function(options) {
          let { id } = options
          this.data.paramA // 页面参数 paramA 的值
          this.data.paramB // 页面参数 paramB 的值
        },
        onShow() {
    
        }
      }
    })

    也可以写在pageLifetimes字段里(去掉on):

    
    Component({
      properties: {
    
      },
    
    
      data: {
        detail: {}
      },
    
      pageLifetimes: {
        load(options) {
          let { id } = options
        },
        show() {
    
        }
      }
    })
    

    二十五、使用组件observers做数据监听器

    可以代替计算属性

      observers: {
        'myBook': function (myBook) {
          this.update(myBook)
          let totalPrice = 0, totalCount = 0
          myBook.filter(item => item.checked).forEach(item => {
            totalCount += item.count
            totalPrice += item.count * item.price
          })
          let total = {
            totalCount,
            totalPrice,
            selectedAll: myBook.length === myBook.filter(item => item.checked).length && myBook.length > 0
          }
          this.setData({
            total
          })
        }
      },

    二十六、antd移动版

    https://mobile.ant.design/components/carousel-cn/

    github源码:

    https://github.com/baweireact/m-app-1706C

  • 相关阅读:
    1407251735-hd-美素数.cpp
    [Javascript] IO Functor
    [AngularJS] Test an Angular Component with $componentController
    [AngularJS] Isolate State Mutations in Angular Components
    [Jest] Track project code coverage with Jest
    [Javascript] Either Functor
    [Javascript] Maybe Functor
    [AngualrJS] ng-strict-di
    [Ramda] Simple log function for debugging Compose function / Using R.tap for logging
    [Jest] Test JavaScript with Jest
  • 原文地址:https://www.cnblogs.com/xutongbao/p/14876304.html
Copyright © 2020-2023  润新知