2048
登录
没  有  难  学  的  前  端
登 录
×
<返回上一级

uni-app小程序客到店项目实战(一):让Vant适用于uni项目

微信小程序作者:折耳

背景

最近一直在试点用uni-app去做一些小需求,分享一下在项目中遇到的问题以及一些经验。ps:本项目整体为vue-cli创建,项目目录结构会与hbuilderx有差异。

项目目标

做一个用户线上预约,线下到店体验的简单预约商城小程序,常见于美业 婚庆/摄影 教育/培训 亲子等线下场景。小程序端使用uni-app,后端API使用nestjs+mongo,服务端部署使用docker

系列连载

(一):让Vant适用于uni项目

(二):uni拦截器(Interceptor)

(三):跨页面通信数据预加载

选择uni-app还是trao?

项目的选型有很多文章,很多分析。抛开项目大小谈性能,纯属于瞎扯。选择主要还是根据团队来,团队里学习vue的是主力,那项目选择uni-app会好一点。反之主力是react那选择trao会好点。没有哪一个框架是没有坑的,要看你是否有解决的能力。

我这里之前的项目都是wepy的,类似vue,所有选择了uni-app去开发,会有更多相似之处。同时我还选择了TypeScript来写uni-app。其实vue2.xts的支持并不美丽,但终究好于js。给自己挖坑。

优雅的使用@vant/weapp

每一个项目的搭建的时候,我都希望能工程化它。尽可能的减少重复的劳动,同时也希望能更好的优化它。

选好项目框架就要去选择对应的ui框架了。@vant/weapp应该会比较适合,毕竟项目是会参考有赞界面的。

前提

得先有一个项目,vue create -p dcloudio/uni-preset-vue vant2uni

@vant/weapp的安装很简单,npm i @vant/weapp -S --production,但是这样并不能用于uni项目。

@vant/weapp是微信小程序原生组件的写法,在uni内微信小程序的原生组件需要放到src/wxcomponents内。

原始的话大概这么用

  1. 有些人会去node_modules目录下找到@vant/weapp然后拷贝到 src/wxcomponents内,大概是大功告成了。

    优点:能下载最新版本的@vant/weapp

    缺点:然后微信开发者调试的时候,提示很多文件无法上传,主要是*.d.ts文件,无碍的(也可以拷贝lib

    目录下的,无*.d.ts文件)。只能手工拷贝同步@vant/weapp版本。只能整体打包进项目。

  2. dcloud插件市场下载。(当初有小伙伴建议使用这种方案)

    优点:没发现

    缺点:版本差异太大了,完全无法同步@vant/weapp版本。只能整体打包进项目。

    ps:版本无法同步,这是交流群里遇到最多的问题,你可能都不知道你下载的是哪个版本。

我是怎么用的?

我们目标很明确:能把任意版本的@vant/weapp文件放到项目的src/wxcomponents文件夹内,去除不必要的*.d.ts文件。这不就是选择性的拷贝嘛?

分析:uni项目是vue-cli创建的,那不就是自带webpack了么。拷贝插件就有现成的copy-webpack-plugin

如何使用wxcomponents内的文件参考官方文档小程序组件支持

新建vue.config.js文件与src目录同级。这里是vue-cli的知识。

const CopyWebpackPlugin = require('copy-webpack-plugin') // 拷贝插件
const path = require('path')
module.exports = {
	chainWebpack: config => {
    // 我这里直接往dist目录拷贝,不拷贝到src了。看过uni源码就知道src/wxcomponents下的文件也是通过拷贝到dist/wxcomponents
		config.plugin('CopyWebpackPlugin')
		.use(new CopyWebpackPlugin([{
      from: path.join(__dirname, `/node_modules/@vant/weapp/dist/`),
      to: path.join(__dirname, `/dist/${process.env.NODE_ENV === 'development' ? 'dev' : 'build'}/mp-weixin/wxcomponents/@vant/weapp/dist/`)
    }], { 
      ignore: ['*.d.ts'] // 忽略文件
    }))
	}
}
复制代码

用法优点不同:在uni项目内,写法就是vue写法了。要抛开@vant/weapp示列的微信原生小程序写法。

// 原生小程序写法示列
<van-button bind:click="click"></van-button>
// uni内 vue语法示列
<van-button @tap="click"></van-button>
复制代码

大功告成了?想要哪个版本的@vant/weapp直接npm i @vant/weapp@x.x.x就可以了。在项目开发模式npm run dev:mp-weixin的时候会自动把你安的 @vant/weapp拷贝到wxcomponents下去。copy-webpack-plugin可以监视拷贝文件的变化,所以就算你更新@vant/weapp版本后也会自动拷贝过去。

以上:已经能做到自动同步@vant/weapp版本了,但是依旧会把整体打包进项目。很多不需要的组件都被拷贝进去了。

进阶使用,删除不需要拷贝的包

使用任何微信自定义组件,都需要在pages.json的里面引入。

微信自定义组件还可能引用其他组件,同样需要在组件目录下的*.jsonusingComponents引入。

有了以上分析,就是读取json文件,获取usingComponents字段,最终获取在项目中使用上的@vant/weapp的组件名称。

新建文件vant2uni.js放在plugins目录下,pluginssrc同级。

// 让Vant用于 uni项目
const chalk = require('chalk')
const path = require('path')
const fs = require('fs')
const get = require('lodash.get')
const stripJsonComments = require('strip-json-comments')
// 默认拷贝目录 有讲究的话可以再具体细分 可能意义不大了
// 这是@vant/weapp内组件公用的地方
let defaultCopy = ['common', 'wxs', 'mixins']
// 独立出来的方法 组件依赖寻找
const deepFindUsingComponents = (jsonPath) =>{
  let jsonFilePath
  if (jsonPath.indexOf('/wxcomponents/') !== -1) {
    jsonFilePath = path.resolve(process.env.UNI_INPUT_DIR, `${jsonPath.replace('/wxcomponents/', '../node_modules/')}.json`)
  } else {
    jsonFilePath = path.resolve(process.env.UNI_INPUT_DIR, `${jsonPath.replace('../', '../node_modules/@vant/weapp/dist/')}.json`)
  }
  let pagesJson = {}
  try {
    pagesJson = JSON.parse(stripJsonComments(fs.readFileSync(jsonFilePath, 'utf8')))
  } catch (error) {}
	let usingComponents = pagesJson.usingComponents || {}
  if (pagesJson.usingComponents) {
		const _deepUsingComponentsPathArr = Object.values(pagesJson.usingComponents) || []
    for (let index = 0; index < _deepUsingComponentsPathArr.length; index++) {
			const obj = _deepUsingComponentsPathArr[index]
      usingComponents = {
        ...usingComponents,
        ...deepFindUsingComponents(obj)
      }
    }
  }
  return usingComponents
}
module.exports = Vant2Uni = () => {
	const jsonFilePath = path.resolve(process.env.UNI_INPUT_DIR, 'pages.json')
	const pagesJson = JSON.parse(stripJsonComments(fs.readFileSync(jsonFilePath, 'utf8')))
	let allUsingComponents = {}
	/**
	 * 获取各个page中的 usingComponents
	 */
	for (let index = 0; index < pagesJson.pages.length; index++) {
		allUsingComponents = {
			...allUsingComponents,
			...get(pagesJson.pages[index], 'style.usingComponents')
		}
	}
	/**
	 * 获取globalStyle中的usingComponents
	 */
	allUsingComponents = {
		...allUsingComponents,
		...get(pagesJson, 'globalStyle.usingComponents', {})
	}
	/**
	 * 组件依赖关系的usingComponents
	 */
	const allUsingComponentsPathArr = Object.values(allUsingComponents)
	for (let index = 0; index < allUsingComponentsPathArr.length; index++) {
		allUsingComponents = {
			...deepFindUsingComponents(allUsingComponentsPathArr[index]),
			...allUsingComponents
		}
	}
	defaultCopy = defaultCopy.concat(Object.keys(allUsingComponents))
	process.stdout.write(chalk.green(`\n*** 拷贝Vant以下组件 ***: ${defaultCopy}\n`))
	return Array.from(defaultCopy, item => {
    // 目录名称没有 van- 要删除
		return item.replace('van-', '')
	})
}
复制代码

修改vue.config.js文件引入vant2uni.js

const CopyWebpackPlugin = require('copy-webpack-plugin')
const path = require('path')
const Vant2Uni = require('./plugins/vant2uni')
const getVantPaths = () => {
  // 默认全拷贝
  let vantPaths = [{
    from: path.join(__dirname, `/node_modules/@vant/weapp/dist/`),
    to: path.join(__dirname, `/dist/dev/mp-weixin/wxcomponents/@vant/weapp/dist/`)
  }]
  if (process.env.NODE_ENV !== 'development') {
    // Vant2Uni 获取具体需要拷贝的文件夹名
    vantPaths = Array.from(Vant2Uni(), item => {
			return {
				from: path.join(__dirname, `/node_modules/@vant/weapp/dist/${item}`),
				to: path.join(__dirname, `/dist/build/mp-weixin/wxcomponents/@vant/weapp/dist/${item}`)
			}
		})
	}
	return vantPaths
}
module.exports = {
	chainWebpack: config => {
    config.plugin('CopyWebpackPlugin')
		.use(new CopyWebpackPlugin(getVantPaths(), { copyUnmodified: true, ignore: ['*.d.ts'] }))
	}
}
复制代码

以上'common', 'wxs', 'mixins'除了这三个目录整体打包其他的,都能做到按需打包进项目了。

写在最后

如果仅仅开发微信小程序项目可以使用@vant/weapp,如果要开发多平台的话不建议在uni项目内使用@vant/weapp了。@vant/weapp并不能适用于其他的小程序。我最终目标是向往多平台开发的。

折腾这么多只是为了能意识到项目需要工程化,提高项目的可维护性,减少不必要人为操作带来的bug。很多小伙伴在vant的群里问,我的mask遮罩怎么不生效,这个怎么跟官方example内不一样,我的是方的它是圆的。这种问题...多半是自身的问题。都不知道用的是哪个年代的版本了然后对照官方最新的example在找差异,浪费的是大家的时间,找到最后发现自己版本过旧了。

本文来源于网络:查看 >
评论
点击刷新
评论
×添加代码片段