业余 Vue.js 选手对于 CSS 布局真的很头疼,因此通过这个 低仿
微信 的练习稍微熟悉一下基本开发,同时开发中涉及到的一点知识做了简单整理。
很多 icon 都是临时找差不多的替代的,真的很低仿
环境
@vue/cli
: 3.0
Demo
1. 效果图
2. iconfont
2.1 使用 iconfont
通过 iconfont 选择想要的图标,下载 iconfont 文件,将下载的文件添加至 assets
目录下,通过以下方式使用
import '@/assets/style/iconfont/iconfont.css'
<div class="iconfont size"></div>
2.2 读取 data 中的 iconfont unicode 编码
// 定义数据
export default {
name: "Search",
data() {
return {
icon: "\ue632"
}
}
}
// 使用
<span class="iconfont"></span>
2.3 placehold 中使用 iconfont
和 2.2
中实现类似
// 定义数据
export default {
name: "Search",
data() {
return {
placeholder: "\ue741 搜索"
}
}
}
<input type="text" class="search-input iconfont" :placeholder="placeholder"/>
3.SCSS
Sass 是世界上最成熟、最稳定、最强大的专业级CSS扩展语言
SCSS
是 Sass 3 引入新的语法,其语法完全兼容 CSS3,并且继承了 Sass 的强大功能。也就是说,任何标准的 CSS3 样式表都是具有相同语义的有效的 SCSS 文件。
由于 SCSS 是 CSS 的扩展,因此,所有在 CSS 中正常工作的代码也能在 SCSS 中正常工作。也就是说,对于一个 Sass 用户,只需要理解 Sass 扩展部分如何工作的,就能完全理解 SCSS。大部分扩展,例如变量、parent references 和 指令都是一致的;唯一不同的是,SCSS 需要使用分号和花括号而不是换行和缩进。
3.1 声明变量
声明
$status-height: 20px;
$header-height: 44px;
使用
.statusBar-wrapper {
// ......
height: $status-height;
}
3.2 @mixin
使用 @mixin
定义的样式可以通过 @include
在任何地方使用
3.2.1 基本使用
声明
@mixin scroll-style {
-webkit-overflow-scrolling: touch; // iOS 滚动回弹
will-change: scroll-position; // 提高性能,提前通知浏览器即将进行的改动
contain: size style layout; // 允许开发者声明当前元素和它的内容尽可能的独立于 DOM 树的其他部分
overflow-x:hidden;
overflow-y: scroll;
}
使用
.scroller-wrapper {
// ......
@include scroll-style;
}
3.2.2 带参数的 @mixin
声明,#000
为默认值,可以不写
@mixin statusBar-style($bgColor: #000) {
width: 100%;
height: $statusBar-height;
background: $bgColor;
}
使用
.statusBar-wrapper {
position: relative;
@include statusBar-style(#eee)
}
4. Vue
4.1路由 Router
4.1.1 嵌套路由
一个 <router-view>
中包含另一个 <router-view>
时,此时要使用嵌套路由
以下路由表示在 app.vue
中通过 <router-view>
打开路径 /wechat
的一个 微信视图,在微信视图中又包含另一个 <router-view>
,可以展示路径分别为 wechat/home
、wechat/addressBook
、wechat/discover
、wechat/me
的四个页面
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
}, {
path: '/wechat',
name: 'wechat',
component: WeChat,
children: [{
path: 'home',
component: WeChatHome
},{
path: 'addressBook',
component: WeChatAddressBook
},{
path: 'discover',
component: WeChatDiscover
},{
path: 'me',
component: WeChatMe
}]
}
]
})
4.1.2 router-link 点击事件 @click
router-link
的 Dom 原生点击事件会被本身的跳转点击覆盖,可以通过 @click.native
只能监听Dom 原生点击事件
<router-link @click.native="selectedIndex = index"></router-link>
4.1.3 重定向
要想访问 localhost:8080
实际访问 localhost:8080/home
可以设置重定向,如下
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [{
path: '/',
component: WeChat,
redirect: '/home',
}]
})
4.1.4 动态路由匹配
4.1.5 路由的动态过渡,类似 iOS push 时动画效果
<template>
<div id="app">
<transition :name="transitionName">
<router-view class="router-view"></router-view>
</transition>
</div>
</template>
<style>
.router-view {
width: 100%;
height: 100%;
position: absolute;
transition: all 0.3s;
}
.slide-left-enter {
opacity: 0;
transform: translate(100%, 0);
}
.slide-left-leave-to {
opacity: 0.8;
/*transform: translate(-100%, 0);*/
}
.slide-right-enter {
opacity: 0;
transform: translate(-100%, 0);
}
.slide-right-leave-to {
opacity: 0.8;
}
</style>
<script>
import WeChat from "@/views/WeChat";
export default {
components: {WeChat},
data() {
return {
transitionName: 'slide-left'
}
},
watch: {
'$route' (to, from) {
const toDepth = to.path.split('/').length;
const fromDepth = from.path.split('/').length;
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left';
}
}
}
</script>
4.2 Style 绑定
可以通过 style 绑定的方式,设置组件样式
<template>
<div>
<div class="header-wrapper" :style="{ background: bgColor, color: color }"></div>
</div>
</template>
export default {
name: "Header",
props: {
bgColor: String,
color: String,
}
}
4.3 获取 Public 静态资源
这里的静态资源指 @vue/cli 3.0
中 public
文件夹的文件
4.3.1 本地 mock
要访问 public 目录下的文件 index.json
可以直接访问 localhost:8080/index.json
// 请求 public 目录下的 mock/index.json 文件
// axios 为请求库
axios.get('/mock/index.json')
4.3.2 本地 image
要访问 public 目录下的文件1.jpg
-
在
public/index.html
或其它通过html-webpack-plugin
用作模板的 HTML 文件中,需要通过<%= BASE_URL %>
设置链接前缀:<link rel="icon" href="<%= BASE_URL %>1.jpg">
-
在模板中,首先需要向组件传入基础 URL
data () { return { publicPath: process.env.BASE_URL } }
然后
<img :src="`${publicPath}1.jpg`">
4.4 路径
4.4.1 src 与 @
@vue/cli 3 中 @
符号表示 src
目录,因此可以使用以下方式表示路径
import HomeHeader from '@/components/home/Header'
但是,虽然 @
符号表示 src
目录,以下写法却是有问题的。因为写成 @
在打包时可以通过该符号确认是 src
路径从而找到路径下的东西,但是使用以下这种相对路径的写法却会在打包时解析不出路径。
// 错误
import HomeHeader from 'src/components/home/Header'
4.4.2 自定义别名
在 vue.config.js
文件修改配置,修改配置后需要重启服务器
module.exports = {
// 设置 webpack
chainWebpack: config => {
// 设置别名
config.resolve.alias
.set('@styles', '@/assets/styles')
}
};
或者这个方式
let path = require('path');
function resolve (dir) {
return path.join(__dirname, dir)
}
module.exports = {
// 设置 webpack
chainWebpack: config => {
// 设置别名
config.resolve.alias
.set('@styles', resolve('src/assets/styles'))
}
};
使用
// 表示的实际路径为 src/assets/styles/reset.css
import '@styles/reset.css'
4.4.3 data 中使用本地 image 的相对路径
以下代码上面注释的那种写法会有问题,因为放在模版里是会被 webpack
打包出来。而在 js
里写图片路径其实只是字符串, webpack
不会处理。需要使用 import
、 require
引入
data() {
return {
//url: "../../../assets/logo.png"
url: require("../../../assets/logo.png")
}
}
4.5 代理 proxy
在 vue.config.js
中添加如下代码,实现的功能就是
- 如一个接口请求
axios.get('/api/index.json')
,那么通过重定向后实际请求的地址为axios.get('http://localhost:8080/mock/index.json')
target
表示代理的目标地址changeOrigin
表示是否支持重定向pathRewrite
重写路径
module.exports = {
// ........
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
pathRewrite: {
'^/api' : '/mock'
}
}
}
}
};
4.6 禁止点击事件向上冒泡
如下,点击 cell 时为了不触发 mask 的点击,可以在 cell 的使用 @click.stop
禁止点击事件向上冒泡
<template>
<div class="mask" @click="$emit('clickMask')">
<ul>
<li class="cell" @click.stop="$emit('clickCell', index)"></li>
<!-- ...... -->
</ul>
</div>
</template>