8. 注意点
- 关于 页面
对于 关于 的页面,其实是一篇文章来的,根据文章类型 type 来决定的,数据库里面 type 为 3
的文章,只能有一篇就是 博主介绍 ;达到了想什么时候修改内容都可以。
所以当 当前路由 === '/about' 时就是请求类型为 博主介绍 的文章。
type: 3, // 文章类型: 1:普通文章;2:是博主简历;3 :是博主简介;
- 移动端适配
移动端使用 rem 单位适配。
// 屏幕适配( window.screen.width / 移动端设计稿宽 * 100)也即是 (window.screen.width / 750 * 100) ——*100 为了方便计算。即 font-size 值是手机 deviceWidth 与设计稿比值的 100 倍 document.getElementsByTagName('html')[0].style.fontSize = window.screen.width / 7.5 + 'px';
如上:通过查询屏幕宽度,动态的设置 html 的 font-size 值,移动端的设计稿大多以宽为 750 px 来设置的。
比如在设计图上一个 150 * 250 的盒子(单位 px):
原本在 css 中的写法:
width: 150px; heigth: 250px;
通过上述换算后,在 css 中对应的 rem 值只需要写:
width: 1.5rem; // 150 / 100 rem heigth: 2.5rem; // 250 / 100 rem
如果你的移动端的设计稿是以宽为 1080 px 来设置的话,就用 window.screen.width / 10.8 吧。
9. 踩坑记
- 1. 让 vue 识别全局方法/变量
- 我们经常在 main.ts 中给 vue.prototype 挂载实例或者内容,以方便在组件里面使用。
import service from "./utils/https"; import urls from "./utils/urls"; Vue.prototype.$https = service; // 其他页面在使用 axios 的时候直接 this.$http 就可以了 Vue.prototype.$urls = urls; // 其他页面在使用 urls 的时候直接 this.$urls 就可以了
然而当你在组件中直接 this.$http 或者 this.$urls 时会报错的,那是因为 $http 和 $urls 属性,并没有在 vue 实例中声明。
- 再比如使用 Element-uI 的 meesage。
import { Message } from "element-ui"; Vue.prototype.$message = Message;
之前用法如下图:
this.$message({ message: '恭喜你,这是一条成功消息', type: 'success' })
然而还是会报错的。
再比如 监听路由的变化:
import { Vue, Watch } from "vue-property-decorator"; import Component from "vue-class-component"; import { Route } from "vue-router"; @Component export default class App extends Vue { @Watch("$route") routeChange(val: Route, oldVal: Route) { // do something } }
只是这样写的话,监听 $route 还是会报错的。
想要以上三种做法都正常执行,就还要补充如下内容:
在 src 下的 shims-vue.d.ts 中加入要挂载的内容。 表示 vue 里面的 this 下有这些东西。
import VueRouter, { Route } from "vue-router"; declare module "vue/types/vue" { interface Vue { $router: VueRouter; // 这表示this下有这个东西 $route: Route; $https: any; // 不知道类型就定为 any 吧(偷懒) $urls: any; $Message: any; } }
- 2. 引入的模块要声明
比如 在组件里面使用 window.document 或者 document.querySelector 的时候会报错的,npm run build 不给通过。
再比如:按需引用 element 的组件与动画组件:
import { Button } from "element-ui"; import CollapseTransition from "element-ui/lib/transitions/collapse-transition";
npm run serve 时可以执行,但是在 npm run build 的时候,会直接报错的,因为没有声明。
正确做法:
我在 src 下新建一个文件 shime-global.d.ts ,加入内容如下:
// 声明全局的 window ,不然使用 window.XX 时会报错 declare var window: Window; declare var document: Document; declare module "element-ui/lib/transitions/collapse-transition"; declare module "element-ui";
当然,这个文件你加在其他地方也可以,起其他名字都 OK。
但是即使配置了以上方法之后,有些地方使用 document.XXX ,比如 document.title 的时候,npm run build 还是通过不了,所以只能这样了:
<script lang="ts"> // 在用到 document.XXX 的文件中声明一下即可 declare var document: any; // 此处省略 XXXX 多的代码 </script>
- 3. this 的类型检查
比如之前的 事件的节流(throttle)与防抖(debounce)方法:
export function throttle(fn: Function, delay: number) { return function() { // 保留调用时的 this 上下文 let context = this; }
function 里面的 this 在 npm run serve 时会报错的,因为 tyescript 检测到它不是在类(class)里面。
正确做法:
在根目录的 tsconfig.json 里面加上 "noImplicitThis": false ,忽略 this 的类型检查。
// 忽略 this 的类型检查, Raise error on this expressions with an implied any type. "noImplicitThis": false,
- 4. import 的 .vue 文件
import .vue 的文件的时候,要补全 .vue 的后缀,不然 npm run build 会报错的。
比如:
import Nav from "@/components/nav"; // @ is an alias to /src import Footer from "@/components/footer"; // @ is an alias to /src
要修改为:
import Nav from "@/components/nav.vue"; // @ is an alias to /src import Footer from "@/components/footer.vue"; // @ is an alias to /src
- 5. 装饰器 @Component
报错。
<script lang="ts"> import { Vue, Component } from "vue-property-decorator"; export default class LoadingCustom extends Vue {} </script>
以下才是正确,因为这里的 Vue 是从 vue-property-decorator import 来的。
<script lang="ts"> import { Vue, Component } from "vue-property-decorator"; @Component export default class LoadingCustom extends Vue {} </script>
- 6. 路由的组件导航守卫失效
vue-class-component 官网里面的路由的导航钩子的用法是没有效果的 Adding Custom Hooks
路由的导航钩子不属于 Vue 本身,这会导致 class 组件转义到配置对象时导航钩子无效,因此如果要使用导航钩子需要在 router 的配置里声明(网上别人说的,还没实践,不确定是否可行)。
- 7. tsconfig.json 的 strictPropertyInitialization 设为 false,不然你定义一个变量就必须给它一个初始值。
- position: sticky;
本项目中的文章详情的目录就是用了 sticky。
.anchor { position: sticky; top: 213px; margin-top: 213px; }
position:sticky 是 css 定位新增属性;可以说是相对定位 relative 和固定定位 fixed 的结合;它主要用在对 scroll 事件的监听上;简单来说,在滑动过程中,某个元素距离其父元素的距离达到 sticky 粘性定位的要求时(比如 top:100px );position:sticky 这时的效果相当于 fixed 定位,固定到适当位置。
用法像上面那样用即可,但是有使用条件:
1、父元素不能 overflow:hidden 或者 overflow:auto 属性。
2、必须指定 top、bottom、left、right 4 个值之一,否则只会处于相对定位
3、父元素的高度不能低于 sticky 元素的高度
4、sticky 元素仅在其父元素内生效
- 8. eslint 报找不到文件和装饰器的错
App.vue 中只是写了引用文件而已,而且 webpack 和 tsconfig.josn 里面已经配置了别名了的。
import Nav from "@/components/nav.vue"; // @ is an alias to /src import Slider from "@/components/slider.vue"; // @ is an alias to /src import Footer from "@/components/footer.vue"; // @ is an alias to /src import ArrowUp from "@/components/arrowUp.vue"; // @ is an alias to /src import { isMobileOrPc } from "@/utils/utils";
但是,还是会报如下的错:
只是代码不影响文件的打包,而且本地与生产环境的代码也正常,没报错而已。
这个 eslint 的检测目前还没找到相关的配置可以把这些错误去掉。
- 9. 路由模式修改为 history
因为文章详情页面有目录,点击目录时定位定相应的内容,但是这个目录定位内容是根据锚点来做的,如果路由模式为 hash 模式的话,本来文章详情页面的路由就是 #articleDetail 了,再点击目录的话(比如 #title2 ),会在 #articleDetail 后面再加上 #title2,一刷新会找不到这个页面的。
10. Build Setup
# clone git clone https://github.com/biaochenxuying/blog-vue-typescript.git
# cd cd blog-vue-typescript
# install dependencies npm install
# Compiles and hot-reloads for development npm run serve
# Compiles and minifies for production npm run build
### Run your tests npm run test
### Lints and fixes files npm run lint
### Run your unit tests npm run test:unit
- Customize configuration
如果要看有后台数据完整的效果,是要和后台项目 blog-node 一起运行才行的,不然接口请求会失败。
虽然引入了 mock 了,但是还没有时间做模拟数据,想看具体效果,请稳步到我的网站上查看 https://biaochenxuying.cn
11. 项目地址与系列相关文章
基于 Vue + TypeScript + Element 的 blog-vue-typescript 前台展示: https://github.com/biaochenxuying/blog-vue-typescript
基于 react + node + express + ant + mongodb 的博客前台,这个是笔者之前做的,效果和这个类似,地址如下:
blog-react 前台展示: https://github.com/biaochenxuying/blog-react