文章目录
4【项目】旺财 Vue 项目搭建
4.1 课前准备
4.2 使用@vue/cli创建项目
4.3 目录结构说明
4.4 添加代码片段snippets
4.5 JS或TS里使用@
4.6 CSS或SCSS里使用~@
5【项目】旺财 Vue 导航栏
5.1 使用VueRouter
5.2 讲Nav组件做成全局组件
5.3 VueRouter 404页面
5.4 用Fixed还是Flex布局
5.5 Layout组件 & slot插槽 - 我与重复不共戴天
5.6 使用svg-sprite-loader引入icon
5.7 eslint 报错如何解决
5.8 如何 import 一个目录
5.9 封装 icon 组件
5.10 添加导航栏CSS样式
5.11 active-class的使用(路由激活)
5.12更新 meta viewport
6 【项目】SVG 的两个坑
6.1 svgo-loader 删除 fill
6.2
6.3
6.4 你遇到最难的技术问题是什么
6.5 vue.config.js 报 eslint 错误怎么办?
7【项目】Money.vue 组件(上)
7.1 整体思路
7.2 CSS思路
7.3 可抄代码CSS第一部分
7.4 可抄代码CSS第二 三部分
7.5 可抄代码CSS第四部分
7.6 可抄代码CSS布局
7.7 模块化
8【项目】Money.vue 组件(下)
8.1 JS组件
8.2 TS组件
8.3 TS组件@Prop装饰器
8.4 TS的本质
8.5 Vue单文件的写法
8.6 numberPad 模块
8.7 notes 模块 - v-model
8.8 tags 模块
9【项目】保存至 LocalStorage
9.1 收集四个组件的value
9.2 使用.sync
9.3 使用LocalStorage
9.4 选看: 数据迁移策略
10【项目】标签页 + 标签编辑页
10.1 model.js
10.2 model.ts
10.3 Label.vue之HTML
10.4 可抄: 10.4 Label.vue之CSS
10.5 新建标签功能
10.6 EditLabel.vue & Vue Router
10.7 如何封装通用组件
10.8 可抄: EditLabel.vue之CSS
10.9 EditLabel.vue功能实现
10.10 ID生成器
11【项目】Vue 全局数据管理(上)
11.1 再次封装recordListModel
11.2 用window来封装API 1
11.3 用window来封装API 2
11.4 消除对window的依赖
11.5 将model融合进store
11.6 修复Tags.vue的bug
11.7 store的bug之值与地址
11.8 小技巧:把store2编程this.$store2(不用跟着做)
12 【项目】Vue 全局数据管理(下)之 Vuex
12.1 Vuex初体验 - 数据读写
12.2 在Money.vue中使用Vuex
12.3 重构Tags.vue和Labels.vue
12.4 在TS里面使用mixin(重新上传)
12.5 重构EditLabel.vue
12.6 在TS里使用computed要用getter语法
12.7 继续重构EditLabel.vue
12.8 Vuex总结(后续课程还有更多总结)
13 【项目】列表展示怎么做
13.1 封装tabs,使用deep语法
13.2 用JS配置height
13.3 用列表展示数据
13.4 可抄袭:添加CSS
13.5 ISO8601 和 dayjs
13.6 数据排序
13.7 数据排序后分组
13.8 完成统计页面
14 【项目】旺财本地版项目总结
14.1 用了哪些知识
14.2 哪些地方可以改进:吃自己的狗粮
14.3手机调试三种方式:局域网、远程调试、vConsole
14.4 切忌雷同,项目描述怎么写
14.5 修复4个commit引起的bug
14.6 部署到GitHub & 设置publicPath
14.7 部署到码云,加快访问速度
14.8 后续计划
15 集成 Echarts
4【项目】旺财 Vue 项目搭建
4.1 课前准备
4.2 使用@vue/cli创建项目
4.3 目录结构说明
目录:
public: 一般不会变动
src: 源代码source的简写src
assets(资源):除了HTML, CSS, JS, TS都放在这里. 比如图片, svg
components: 只放组件
router: 用来放路由
store:
views: 来放视图的
App.vue: 整个应用的视图
Main.ts: 入口文件, 主要功能来渲染App
registerServiceWorker.ts: 与PWA相关
shims-tsx.d.ts: TS相关的
shims-vue.d.ts: TS相关的
tests: 测试相关
下面都是配置文件
tsconfig.json: TS配置
vue.config.js: webpack配置
4.4 添加代码片段snippets
编辑器的配置:
webstorm修改默认的vue模版
4.5 JS或TS里使用@
4.6 CSS或SCSS里使用~@
选择no, 我们在webpack配置不在webstorm配置
可以执行, 视频中的webstorm有红线, 自己的最新的2020.2的webstorm修复了这个bug.
5【项目】旺财 Vue 导航栏
5.1 使用VueRouter
HEAD表示当前版本
git reset --hard HEAD
1
默认直接找到router目录下的index.ts
import router from ‘./router’
1
new Vue({
router,
store,
render: h => h(App)
}).KaTeX parse error: Expected 'EOF', got '#' at position 8: mount('#̲app') //等价 new …mount(’#app’)
1
2
3
4
5
6
7
8
9
10
11
lint-staged用来检测代码是否出错
control+tab切换文件
5.2 讲Nav组件做成全局组件
首先考虑到直接将三个导航按钮写入到App.vue中, 要是有些页面不需要三个导航按钮呢.
因此, 需要将这三个导航按钮抽象成一个组件, 这样直接给Money.vue, Labels.vue和Statistics.vue引用
然后发现相同的代码引用了3次, 为啥不直接全局引用到main.ts中呢
自己练习过程中就是不断试错的过程, 需要自己把坑都走过了, 知道哪有坑就走的顺畅了.
拒绝直接给标准答案的方式教学
可以右击项目文件夹后, git commit
5.3 VueRouter 404页面
路由没有已知的页面, 就跳转到404
5.4 用Fixed还是Flex布局
@@@
千万别在手机上用Fixed
@@经验, 忠告@
加scoped后, 对应的class地方的标签出会出现data-v-xxxxx,
自动会在写该class的时候加上该部分(属性选择器)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
等价于直接加scope
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@@@
只要能加scoped的地方都需要加, App.vue除外
@@经验, 忠告@
@@@
复制3次就是bug
@@理念@
5.5 Layout组件 & slot插槽 - 我与重复不共戴天
5.6 使用svg-sprite-loader引入icon
安装svg-sprite-loader
yarn add svg-sprite-loader -D
1
因为github上没有vue配置, 需要将webpack转一下.
vue.config.js
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require(‘path’)
module.exports = {
lintOnSave: false,
chainWebpack: config => {
const dir = path.resolve(__dirname, ‘src/assets/icons’)
// 配置svg-sprite-loader
config.module.rule('svg-sprite').test(/\.svg$/).include.add(dir).end() //包含 icons 目录.use('svg-sprite-loader').loader('svg-sprite-loader').options({extract: false}).end()//配置插件
config.plugin('svg-sprite')// eslint-disable-next-line @typescript-eslint/no-var-requires.use(require('svg-sprite-loader/plugin'), [{plainSprite: true}])config.module.rule('svg').exclude.add(dir) // 其他 svg loader 排除 icons 目录
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
5.7 eslint 报错如何解决
5.8 如何 import 一个目录
import icon目录下的所有svg
// import svg 文件夹
const importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);
try {
importAll(require.context(’…/assets/icons’, true, /.svg$/));
} catch (error) {
console.log(error);
}
1
2
3
4
5
6
7
8
5.9 封装 icon 组件
图标宽高一般用em
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
1
2
3
4
5
6
7
5.10 添加导航栏CSS样式
@@@
不是一个标签
@@了解了@
@@@
用阴影的标准: 不能让别人看出用阴影
@@诀窍@
@@@
能不写高度就不要写高度
@@经验@
5.11 active-class的使用(路由激活)
5.12更新 meta viewport
更新 meta viewport
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
1
6 【项目】SVG 的两个坑
6.1 svgo-loader 删除 fill
.use(‘svgo-loader’).loader(‘svgo-loader’)
.tap(options => ({…options, plugins: [{removeAttrs: {attrs: ‘fill’}}]})).end()
1
2
下载svgo-loader
yarn add --dev svgo-loader
1
但是可能会出现把svg图片自己的fill删掉这样导致, 图片无法正常显示.
6.2
6.3
6.4 你遇到最难的技术问题是什么
6.5 vue.config.js 报 eslint 错误怎么办?
把这句话添加到 vue.config.js 的第一行即可
/* eslint-disable */
1
7【项目】Money.vue 组件(上)
7.1 整体思路
@@@
一个文件有150行左右, 一般需要插分多个文件
@@经验@
包裹 衣 食 住 行, 选中该4行
ss 输入 surround in emmet, 然后输入li* 表示每行包裹, 不带表示4行整体包裹
7.2 CSS思路
@@@
写CSS步骤:
reset
清空默认不需要的样式
reset.scss
- {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a{
text-decoration: none;
color: inherit;
}
1
2
3
4
5
6
7
8
9
10
全局(字体, 行高)
字体一般用黑体, 跨平台中文字体解决方案
字体写在#app上还是body上, 主要看这个项目几个人负责, 多人负责写#app上防止冲突. 单人的话建议body, 防止写样式出了#app, 而达不到整体影响的作用.
网站字体一般不用黑色, 推荐使用#333
helper.scss
$font-hei: -apple-system, “Noto Sans”, “Helvetica Neue”, Helvetica, “Nimbus Sans L”, Arial, “Liberation Sans”, “PingFang SC”, “Hiragino Sans GB”, “Noto Sans CJK SC”, “Source Han Sans SC”, “Source Han Sans CN”, “Microsoft YaHei”, “Wenquanyi Micro Hei”, “WenQuanYi Zen Hei”, “ST Heiti”, SimHei, “WenQuanYi Zen Hei Sharp”, sans-serif;
1
app.vue
body {
// 苹果设备上有用的
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #333;
font-family: $font-hei;
//默认行高
line-height: 1.5;
}
1
2
3
4
5
6
7
8
9
变量
控制变量, 变量放helper.scss, 这个文件只能放变量, 只能放变量, 只能放变量. 因为最终转为css这个文件中的东西都会消失.
#f00表示纯红色
在这里插入图片描述
局部
@@经验@
@@@
不要在自己的代码中, 留下任何无用的代码, 包括注释
@@忠告@
7.3 可抄代码CSS第一部分
@@@
如果布局复杂就从里往外, 简单的话就随便
@@忠告@
重置默认li, ol样式
ul, ol{
list-style: none;
}
1
2
3
border-radius: 50% 是高度的50%, 不是宽度的50%
宽度的50%:
height: 24px;
border-raduis: 12px
//等价
height: 24px;
border-raduis: (24px/2)
//等价
h : 24 p x ; h e i g h t : h: 24px; height: h:24px;height:h;
border-radius: $h/2;
1
2
3
4
5
6
7
8
9
10
11
button input默认字体是宋体,需要到reset.scss重置一下
button, input{
font: inherit;
}
1
2
3
垂直居中方法:
1 用flex布局来
2 用height和line-height来(注意只能是一行的内容用这个)
border-bottom可以不写颜色, 这样就可以随字体颜色
7.4 可抄代码CSS第二 三部分
line-height默认是有高度的.
垂直水平居中能用flex就用flex.
7.5 可抄代码CSS第四部分
编程字体1和0一样宽, 等宽字体, 默认用计算机自带的
font-family: Consolas, monospace;
1
flex布局解决不了, 就可以用float布局了(用了float父元素就要用clearfix)
可用rgba或fade_out
box-shadow: inset 0 3px 3px -3px fade_out(black, 0.3);
//或
box-shadow: inset 0 3px 3px -3px rgba(0, 0, 0, 0.25)
1
2
3
7.6 可抄代码CSS布局
不是太影响用户体验的部分可以暂时不优化, 优化必须优化的部分.
7.7 模块化
代码过150行就需要模块化, 养成好习惯
8【项目】Money.vue 组件(下)
TS的好处:
类型提示:更智能的提示
编译时报错:还没运行代码就知道自己写错了
类型检查:无法点出错误的属性
8.1 JS组件
prop传过来来的值一般用mounted处理
8.2 TS组件
ts新语法就是给type添加类型string
8.3 TS组件@Prop装饰器
查看包的最新版本
npm info typescript version
1
查看当前安装的包的版本
npm ls typescirpt
或
yarn list typescript
1
2
3
安装好之后需要File->invalidate Caches/…
使用第三方vue-property-decorator来使用ts的prop
//Prop 告诉 Vue, xxx不是 data 是 prop
//Number 告诉 Vue, xxx 运行时, 是个Number
//xxx 属性名
//number | undefined 告诉 TS xxx 的编译时的类型
@Prop(Number) xxx: number | undefined
1
2
3
4
5
8.4 TS的本质
8.5 Vue单文件的写法
写 Vue 组件的三种方式(单文件组件)
用JS对象:
export default { data, props, methods, created, …}
1
用 TS 类
@Component
export default class XXX extends Vue{
xxx: string = ‘hi’;
@Prop(Number) xxx: number|undefined;
}
1
2
3
4
5
用 JS 类
@Component
export default class XXX extends Vue{
xxx = ‘hi’
}
1
2
3
4
8.6 numberPad 模块
数字键盘逻辑:
1 当前为0
直接输入0-9需要把0变为对应的数
当时.时,需要追加成0.
2不能出现两个.
删除逻辑:
1 利用字符串slice来删除最后一个
2 output只有1位时, output变为0
8.7 notes 模块 - v-model
.
.
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
:value=“value” @input="value = $event.target.value"可以用一下代码替换v-model=‘value’
8.8 tags 模块
…展开运算符, 扩展运算符
@@@
不能直接操作外部数据
eg: Tags.vue中的dataSource, 应该传给Money.vue修改
@@职业素养@
9【项目】保存至 LocalStorage
9.1 收集四个组件的value
@@@
子组件的数据要汇集到父组件上
@@经验@
@@@
外面的数据由外面的vue控制, 包括初始值, 里面的Vue只是只读就行了.
@@素养@
9.2 使用.sync
9.3 使用LocalStorage
深拷贝
const record2 = JSON.parse(JSON.stringify(this.record))
1
9.4 选看: 数据迁移策略
10【项目】标签页 + 标签编辑页
10.1 model.js
TS项目引入JS需要用require
const model = require(’@/model.js’).model;
1
10.2 model.ts
xxx.d.ts表示定义(definition)的文件会在该部分定义了, 其他部分直接使用.
怎么把JS文件改为TS:
第一: 改文件名后缀
第二: 给:添加类型
10.3 Label.vue之HTML
10.4 可抄: 10.4 Label.vue之CSS
button(内联元素)怎么居中: text-align: center, 应加到父元素上
padding 影响bg的范围
10.5 新建标签功能
10.6 EditLabel.vue & Vue Router
新生最怕改代码
10.7 如何封装通用组件
重命名步骤:
1 修改文件名
2 修改类名
3 全局查找
10.8 可抄: EditLabel.vue之CSS
10.9 EditLabel.vue功能实现
10.10 ID生成器
ID的原则:
1 一旦给了ID, 就不要修改
2 ID不能重复
lib文件夹一般写自己的库
11【项目】Vue 全局数据管理(上)
11.1 再次封装recordListModel
11.2 用window来封装API 1
custom.d.ts好像不需要引用就可以用, 自动引用的.
11.3 用window来封装API 2
用window带来的问题, 全局变量太多了. 严重依赖window
11.4 消除对window的依赖
TS注释不要顶到第一列:
11.5 将model融合进store
11.6 修复Tags.vue的bug
11.7 store的bug之值与地址
11.8 小技巧:把store2编程this.$store2(不用跟着做)
全局状态管理(也叫全局数据管理)的好处是什么?
解耦:将所有数据相关的逻辑放入 store(也就是 MVC 中的 Model,换了个名字而已)
数据读写更方便:任何组件不管在哪里,都可以直接读写数据
控制力更强:组件对数据的读写只能使用 store 提供的 API 进行(当然也不排除有猪队友直接对 tagList 和 recordList 进行 push 等操作,这是没有办法禁止的)
12 【项目】Vue 全局数据管理(下)之 Vuex
12.1 Vuex初体验 - 数据读写
mutations中没有this
红线部分需要加$后才可以这样使用,否则需要写一个方法。
12.2 在Money.vue中使用Vuex
12.3 重构Tags.vue和Labels.vue
12.4 在TS里面使用mixin(重新上传)
参考官方mixins
@@@
类才首字母大写,对象首字母不大写。
@@习惯@
12.5 重构EditLabel.vue
mutation只能调不能获取返回值,所有不需要return
12.6 在TS里使用computed要用getter语法
新版webstorm修复了这个bug
如果遇到这个问题,可以用ES6新语法getter来替代computed
12.7 继续重构EditLabel.vue
12.8 Vuex总结(后续课程还有更多总结)
13 【项目】列表展示怎么做
13.1 封装tabs,使用deep语法
使用scoped情况下控制子组件样式,且不污染子组件自身的样式,使用::deep语法来实现最好。
1
2
3
4
5
最佳实践classPrefix,防止CSS干扰。
常量是一个数组是可以push的,就是要冻住常量数组不能改变。需要用到Object.freeze([])
可以有一个class和:class
要是CSS不改变,可以降低内部优先级,或者升高外部的优先级。
13.2 用JS配置height
这是演示,方方一般不用JS来控制CSS。
13.3 用列表展示数据
时间:ISO 8601,是需要学会的。
JSON不支持Date类型
声明一个空对象的类型:
const hashTable: {[key: string]: RecordItem[]} = {};
1
13.4 可抄袭:添加CSS
ol可以代替div
local storage最多存5M到10M数据
要做测试,比如备注字数很多情况。
13.5 ISO8601 和 dayjs
ISO8601:合并表示时,要在时间前面加一大写字母T,如要表示东八区时间2004年5月3日下午5点30分8秒,可以写成2004-05-03T17:30:08+08:00或20040503T173008+08。
得到一个ISO8601时间
let time = new Date()
time // Mon Oct 12 2020 00:40:39 GMT+0800 (中国标准时间)
let timeISO = time.toISOString()
timeISO // “2020-10-11T16:41:03.150Z”
let timeStamp = Date.parse(timeISO)
timeStamp // 1602434840270
let time2 = new Date(timeStamp)
time2 // Mon Oct 12 2020 00:47:31 GMT+0800 (中国标准时间)
time2.getHours() // 0
1
2
3
4
5
6
7
8
9
10
11
时间相关用IOS8601,时间戳没有时区的概念
一般不用JS的Date
用moment.js,非常好用,但是体积很大18k gz,vue的库才30k,这差不多一半多vue库了。
所以用day.js,是moment.js的压缩版2k。
13.6 数据排序
数组是有序的且key的值为数字字符串的对象。
13.7 数据排序后分组
13.8 完成统计页面
foreach是没有返回值的map,map是有返回值的foreach
14 【项目】旺财本地版项目总结
14.1 用了哪些知识
14.2 哪些地方可以改进:吃自己的狗粮
吃自己的狗粮:自己吃自己的粮都难吃,那就要改进,不然人家咋会用呢?
存在问题:
适配多设备,多浏览器
初始自动创建tag会提示alert提示创建成功
Money 页面备注部分添加一个重置按钮
14.3手机调试三种方式:局域网、远程调试、vConsole
14.4 切忌雷同,项目描述怎么写
改名字
样式(参考优秀的软件)
14.5 修复4个commit引起的bug
14.6 部署到GitHub & 设置publicPath
serve和http-server都可以
通过检测宽度来判断是否在pc端,并生成一个二维码来方便手机访问。
14.7 部署到码云,加快访问速度
14.8 后续计划
15 集成 Echarts
datetime-local只支持到秒的ISO时间显示,毫秒的显示有问题。
HTML 的 date 插浏览器兼容有问题
vue-echarts的tooltip兼容性有问题,所以自己写echarts组件
永远不要用w3schools ,google搜索屏蔽它:css hide scrollbar -w3shools
隐藏scrollbarcss
::-webkit-scrollbar {
display: none;
}
1
2
3
scrollbar最大宽度:
const div = (this.$refs.chartWrapper as HTMLDivElement)
div.scrollLeft = div.scrollWidth;
1
2
lodash