结合项目学习下Vant组件。
Vue2:Vant 2 - Mobile UI Components built on Vue
Vue3:Vant 4 - A lightweight, customizable Vue UI library for mobile web apps.
课程地址:【vue-vant组件库】 https://www.bilibili.com/video/BV1q5411E7iT/?p=9&share_source=copy_web&vd_source=b1cb921b73fe3808550eaf2224d1c155
github地址:GitHub - abigale00/Vue-Vant
一、创建&启动项目
详见Vue2第三部分,创建(vue create demo1)和启动项目(npm run serve)。
二、移动端rem适配
2.1 介绍
Vant 2 - Mobile UI Components built on Vue
进阶用法-浏览器适配-Rem布局适配
Vant 默认使用 px
作为样式单位,如果需要使用 viewport
单位 (vw, h, qvmin, vmax),推荐使用 postcss-px-to-viewport 进行转换。
postcss-px-to-viewport 是一款 PostCSS 插件,用于将 px 单位转化为 vw/vh 单位。
Rem 布局适配
如果需要使用 rem
单位进行适配,推荐使用以下两个工具:
- postcss-pxtorem 是一款 PostCSS 插件,用于将 px 单位转化为 rem 单位
- lib-flexible 用于设置 rem 基准值
2.2 postcss-pxtorem包
2.2.1 安装
GitHub - cuth/postcss-pxtorem: Convert pixel units to rem (root em) units using PostCSS
命令:$ npm install postcss postcss-pxtorem --save-dev
补充:写文档的时候 $ 表示后面是一段指令;$ 后面的内容需要在命令行执行
安装成功(安装前将项目关掉)
查看,package.json
2.2.2 配置
安装完postcss-pxtorem需要配置。创建postcss.config.js文件,复制以下内容。
postcss.config.js是对postcss插件进行配置的。
postcss插件不只有postcss-pxtorem一款,还有一款autoxxxx
照猫画虎。
注意:一般不会改变vant组件库的内置样式(px改rem),那么就需要过滤掉。只需要改变我们自己写的代码,根据设计图把px转为rem。→ 需要使用selectorBacklist,选择器黑名单。
2.3 lib-flexible包
2.3.1 安装
GitHub - amfe/lib-flexible: 可伸缩布局方案
命令:npm i -S amfe-flexible
查看安装是否成功
2.3.2 配置
meta标签
在index.html里替换之前的meta标签
script标签
在这里,在main.js文件里import这个包
到此,移动端适配完成,启动项目。
2.4 rem适配结果
字体设置30px,到页面上转换为0.8rem,这与设置的rootValue有关。
注意:如果样式写为行内样式,那么px不会做rem适配。
2.5 定制主题
但是打不开诶...
简单说下,就是在Vant Demo项目下,vant-rem里做了rem适配。
里面的package.json,里安装了amfe-flexible(生产依赖)和postcss-pxtorem(开发依赖)。
main.js,import了amfe-flexible,
vue.config.js,配置了postcss插件,用的还是postcss-pxtorem.
说明:postcss-pxtorem不只可以配置在postcss.config.js里,还可以配置在vue.config.js里。
up示例了下使用vue.config.js,但我就不改了。
改了配置需要重新编译。from 弹幕
三、安装导入Vant组件库
3.1 安装Vant
命令:npm i vant@latest-v2 -S
(for Vue2)
Vant 2 - Mobile UI Components built on Vue
3.2 引入Vant
可以看下示例工程
GitHub - vant-ui/vant-demo: Collection of vant demos.
引入组件的方式Vant 2 - Mobile UI Components built on Vue
3.2.1 自动按需引入组件-推荐
需要安装配置插件。
1. 安装插件
babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式。
命令:npm i babel-plugin-import -D
安装为开发时依赖
安装成功
package.json
2. 配置插件
3. 导入插件
全局导入-推荐
在main.js中,导入Button,安装Button插件(全局安装)。
一次安装,项目所有文件都可以使用Button组件。
局部导入
在每个使用该vant组件的页面中,单独导入。
<script>
import { Button } from "vant";
export default {
name: "App",
components: {
[Button.name]: Button,
},
};
</script>
import Buton和components注册。
总结
推荐全局导入。
3.2.2 手动按需引入组件
1. 全局注册
在不使用插件的情况下,可以手动引入需要的组件。
使用示例
main.js
import Button from 'vant/lib/button';
import 'vant/lib/button/style';
Vue.use(Button);
注意:结尾需要安装Button,即Vue.use(Button)
Vue.use(Button),全局注册组件,将组件注册为全局组件,在项目里所有页面都可以使用该Vant组件。
全局导入优点:项目所有组件都可以使用全局导入的Vant组件。
2. 局部注册
在需要使用Vant组件的页面导入组件和样式。
例如App.vue里
<script>
import Button from "vant/lib/button";
import "vant/lib/button/style";
export default {
name: "App",
components: {
[Button.name]: Button,
},
};
</script>
引入还是跟全局注册一样的,只是注册要在components中进行。
3. 总结
推荐全局注册,只需要注册一次,局部注册比较麻烦。
3.2.3 导入所有组件
Vant 支持一次性导入所有组件,引入所有组件会增加代码包体积,因此不推荐这种做法。
使用示例
main.js里导入所有组件
import Vue from 'vue';
import Vant from 'vant'; // 引入vant
import 'vant/lib/index.css'; // 导入vant样式文件
Vue.use(Vant); //安装vant插件
注意:Vue.use(Vant);// 安装Vant插件
四、定制主题
Vant 2 - Mobile UI Components built on Vue
Vant 提供了一套默认主题,CSS 命名采用 BEM 的风格,方便使用者覆盖样式。如果你想完全替换主题色或者其他样式,可以按照本文档进行主题定制。
Vant 使用了 Less 对样式进行预处理,并内置了一些样式变量,通过替换样式变量即可定制你自己需要的主题。
例如修改主题色等等。
跳过。
五、添加特定厂商前缀
AutoPrefixer给css样式添加厂商前缀。
安装配置插件。
移动端项目,跑在手机上。手机分安卓和ios系统。
跳过。
六、插槽
通过封装一个按钮组件学习插槽使用。
6.1 匿名插槽
子组件
父组件
效果
补充:eslint报错,解决方法之一
【b站ZSEN就是Huzhushan】Typescript入门并在vue项目中使用-CSDN博客
解决方式2
You may use special comments to disable some warnings.
Use // eslint-disable-next-line to ignore the next line.
Use /* eslint-disable */ to ignore all warnings in a file.
6.2 具名插槽
子组件
父组件
v-slot:icon表示:使用名字为icon的具名插槽。
效果
6.3 父组件访问子组件变量
在父组件使用子组件的变量
6.3.1 父向子传值
step1. 父组件向子组件传值
父组件传递
子组件接收和使用
中间检查
6.3.2 父组件中使用子组件变量
step2 父组件中使用子组件变量
规则:子组件info只能在子组件使用,不可在父组件使用;父组件只能使用父组件变量,不能使用子组件变量。
如果想在父组件的具名插槽里使用子组件的变量,怎么做呢
====================================================================
中间过程(后期可跳过)
子组件定义具名插槽
父组件使用插槽
此时虽然使用了具名插槽,但是第19行的info还是父组件的变量info。
(跳过部分结束)
======================================================================
如果想要在18行的template里使用子组件的变量,可以这样做,继续往下看。
step1 在子组件的具名插槽里绑定要在父组件插槽里的变量
step2 父组件调用子组件的变量
slotProps:(可以是任何名)表示该插槽动态绑定的属性的对象,比如info属性,没有name属性。
===================================================================
这段复习时可以不看
效果
只有info属性
(跳过部分结束)
=================================================================
那么通过slotProps.info就能拿到子组件的info对象了。
效果
感悟:有问题要学会找原因,而不是看有没有写漏代码,要学会debug.
扩展
直接使用对象结构获取属性,对比看下。
七、使用规范
风格指南
Vant 2 - Mobile UI Components built on Vue
组件数据
组件的 data 必须是一个函数。
// bad
export default {
data: {
foo: 'bar',
},
};
// good
export default {
data() {
return {
foo: 'bar',
};
},
};
单文件组件文件名称
单文件组件的文件名应该要么始终是单词大写开头 (PascalCase),要么始终是横线连接 (kebab-case)。
// bad
mycomponent.vue
myComponent.vue
// good
my-component.vue
MyComponent.vue
紧密耦合的组件名
和父组件紧密耦合的子组件应该以父组件名作为前缀命名。
// bad
components/
|- TodoList.vue
|- TodoItem.vue
└─ TodoButton.vue
// good
components/
|- TodoList.vue
|- TodoListItem.vue
└─ TodoListItemButton.vue
自闭合组件
在单文件组件中没有内容的组件应该是自闭合的。
<!-- bad -->
<my-component></my-component>
<!-- good -->
<my-component />
Prop 名大小写
在声明 prop 的时候,其命名应该始终使用 camelCase,而在模板中应该始终使用 kebab-case。
// bad
export default {
props: {
'greeting-text': String,
},
};
// good
export default {
props: {
greetingText: String,
},
};
<!-- bad -->
<welcome-message greetingText="hi" />
<!-- good -->
<welcome-message greeting-text="hi" />
指令缩写
指令缩写,用 :
表示 v-bind:
,用 @
表示 v-on:
<!-- bad -->
<input v-bind:value="value" v-on:input="onInput" />
<!-- good -->
<input :value="value" @input="onInput" />
Props 顺序
标签的 Props 应该有统一的顺序,依次为指令、属性和事件。
(ref是属性)
<my-component
v-if="if"
v-show="show"
v-model="value"
ref="ref"
:key="key"
:text="text"
@input="onInput"
@change="onChange"
/>
组件选项的顺序
组件选项应该有统一的顺序。
export default {
name: '',
mixins: [],
components: {},
props: {},
data() {},
computed: {},
watch: {},
created() {},
mounted() {},
destroyed() {},
methods: {},
};
组件选项中的空行
组件选项较多时,建议在属性之间添加空行。
export default {
computed: {
formattedValue() {
// ...
},
styles() {
// ...
},
},
methods: {
onInput() {
// ...
},
onChange() {
// ...
},
},
};
单文件组件顶级标签的顺序
单文件组件应该总是让顶级标签的顺序保持一致,且标签之间留有空行。
即template最先,script居中,style结尾。
<template>
...
</template>
<script>
/* ... */
</script>
<style>
/* ... */
</style>
直接复制官网内容,标题层级就不改了。
八、Vant基础组件
8.1 Button组件
Vant 2 - Mobile UI Components built on Vue
在App.vue介绍vant组件使用。
之前通过自动按序引入组件已经引入过Button了,这里不再介绍,忘记的话去看3.2.1
注意:vant组件都是van-开头。
使用示例
这个课就是把van-button官网的所有样式都实现一遍。
8.2 Cell单元格
单元格为列表中的单个展示项。
Vant 2 - Mobile UI Components built on Vue
列表吗
8.3 Icon图标
van-icon
Vant 2 - Mobile UI Components built on Vue
用到现看。
8.4 Image图片
项目里没用,不看了。
8.5 Layout布局
项目里没用,不看了。
8.6 Popup弹出层
项目里没用,不看了。
8.7 style内置样式
Vant 2 - Mobile UI Components built on Vue
Vant 中默认包含了一些常用样式,可以直接通过 className 的方式使用。
文字省略
当文本内容长度超过容器最大宽度时,自动省略多余的文本。
<!-- 最多显示一行 -->
<div class="van-ellipsis">这是一段最多显示一行的文字,多余的内容会被省略</div>
<!-- 最多显示两行 -->
<div class="van-multi-ellipsis--l2">
这是一段最多显示两行的文字,多余的内容会被省略
</div>
<!-- 最多显示三行 -->
<div class="van-multi-ellipsis--l3">
这是一段最多显示三行的文字,多余的内容会被省略
</div>
1px 边框
为元素添加 Retina 屏幕下的 1px 边框(即 hairline),基于伪类 transform 实现。
<!-- 上边框 -->
<div class="van-hairline--top"></div>
<!-- 下边框 -->
<div class="van-hairline--bottom"></div>
<!-- 左边框 -->
<div class="van-hairline--left"></div>
<!-- 右边框 -->
<div class="van-hairline--right"></div>
<!-- 上下边框 -->
<div class="van-hairline--top-bottom"></div>
<!-- 全边框 -->
<div class="van-hairline--surround"></div>
动画
可以通过 transition
组件使用内置的动画
<!-- 淡入 -->
<transition name="van-fade">
<div v-show="visible">Fade</div>
</transition>
<!-- 上滑进入 -->
<transition name="van-slide-up">
<div v-show="visible">Slide Up</div>
</transition>
<!-- 下滑进入 -->
<transition name="van-slide-down">
<div v-show="visible">Slide Down</div>
</transition>
<!-- 左滑进入 -->
<transition name="van-slide-left">
<div v-show="visible">Slide Left</div>
</transition>
<!-- 右滑进入 -->
<transition name="van-slide-right">
<div v-show="visible">Slide Right</div>
</transition>
8.8 Toast轻提示
Vant 2 - Mobile UI Components built on Vue
样式自己去看。
文字提示
Toast('提示内容');
加载提示
使用 Toast.loading
方法展示加载提示,通过 forbidClick
属性可以禁用背景点击。
Toast.loading({
message: '加载中...',
forbidClick: true,
});
成功/失败提示
使用 Toast.success
方法展示成功提示,使用 Toast.fail
方法展示失败提示。
Toast.success('成功文案');
Toast.fail('失败文案');
自定义图标
通过 icon
选项可以自定义图标,支持传入图标名称或图片链接,通过loadingType
属性可以自定义加载图标类型。
Toast({
message: '自定义图标',
icon: 'like-o',
});
Toast({
message: '自定义图片',
icon: 'https://img01.yzcdn.cn/vant/logo.png',
});
// 自定义加载图标
Toast.loading({
message: '加载中...',
forbidClick: true,
loadingType: 'spinner',
});
自定义位置
Toast 默认渲染在屏幕正中位置,通过 position
属性可以控制 Toast 展示的位置。
Toast({
message: '顶部展示',
position: 'top',
});
Toast({
message: '底部展示',
position: 'bottom',
});
动态更新提示
执行 Toast 方法时会返回对应的 Toast 实例,通过修改实例上的 message
属性可以实现动态更新提示的效果。
const toast = Toast.loading({
duration: 0, // 持续展示 toast
forbidClick: true,
message: '倒计时 3 秒',
});
let second = 3;
const timer = setInterval(() => {
second--;
if (second) {
toast.message = `倒计时 ${second} 秒`;
} else {
clearInterval(timer);
// 手动清除 Toast
Toast.clear();
}
}, 1000);
全局方法
引入 Toast 组件后,会自动在 Vue 的 prototype 上挂载 $toast
方法,便于在组件内调用。
export default {
mounted() {
this.$toast('提示文案');
},
};
单例模式
Toast 默认采用单例模式,即同一时间只会存在一个 Toast,如果需要在同一时间弹出多个 Toast,可以参考下面的示例:
Toast.allowMultiple();
const toast1 = Toast('第一个 Toast');
const toast2 = Toast.success('第二个 Toast');
toast1.clear();
toast2.clear();
修改默认配置
通过 Toast.setDefaultOptions
函数可以全局修改 Toast 的默认配置。
// 将所有 Toast 的展示时长设置为 2000 毫秒
Toast.setDefaultOptions({ duration: 2000 });
// 将所有 loading Toast 设置为背景不可点击
Toast.setDefaultOptions('loading', { forbidClick: true });
// 重置所有 Toast 的默认配置
Toast.resetDefaultOptions();
// 重置 loading Toast 的默认配置
Toast.resetDefaultOptions('loading');
总结:其实学到的更多还是前面七节内容(除去四和五)。