第一天:导航栏
今天完成了阿花记账的导航栏。制作过程中使用了Vue-Router
-
router/index.ts添加router,配置4个路径对应组件
-
初始化组件
-
将router传给new Vue()
-
在App组件里用
<router-view/>给出router渲染区域 -
切换路径切换页面
<router-link to=""></router-link> -
找不到页面,进行动态路由匹配(看上去挺高大上,其实就是除了我们设置的页面的其他页面)
听说手机页面布局的时候如果使用fixed进行布局会有很多坑,所以选择用了flex布局
还学到了一个知识。就是SCSS里有一个属性是scope ,这个的作用有两个:
- 在你的div上加一个属性:data-v-xxx
- 在CSS上加一个上面的属性选择器。主要是用于匹配
- 只要能加scope就加scope,这样可以避免class冲突。但是如果是全局设置属性就不要加scope了,例如body{}
Vue插槽
- 将代码简化,封装,调用。创建
<layout></layout> - 将重复的部分放在一个组件里,不重复的部分放在插槽里
使用svg-sprite-loader引入icon
- svg其实就是一个xml
- 有个难点鸭,怎么把webpack.config.js配置转换成Vu.config.js
- 在body里创建一个svg标签,svg标签里创建symbol标签,每个symbol有个id。
<use xlink:href="#iconname"/> - 将一个目录里任意后缀的文件统一全部引入到当前文件。
let importAll = (requireContext: __WebpackModuleApi.RequireContext) => requireContext.keys().forEach(requireContext);</br>
try {importAll(require.context('../assets/icons', true, /\.svg$/));} catch (error) {console.log(error);}
对icon组件进行封装
- 代码重复太多惹!怎么办!封装!ps:icon是全局都可以引用的,记得在main.ts把它定义为全局的。
- 给icon设置name属性。
- 使用v-bind将icon的name绑定到svg上.注意xlink前面的:
<svg class="icon" @click="$emit('click', $event)">
<use :xlink:href="'#'+name"/>
</svg>
怎么设置路由激活呢(点击链接,链接高亮)? 答:给router-link添加active-class="selected"属性。点击的时候整个页面先消失,然后出现新的nav页面。路由和to值匹配,进行高亮
第三天:完成Money组件
感触:
- 模块化:写代码的时候发现Money组件里CSS代码放在一起也太多了!!把Money页面分成了四个部分,每个部分拥有他们自己CSS代码。其实也就是模块化对吧。
- TypeScript就是JS+Type。重点就是JS的七个基础类型(六个简单类型,一个负责类型) 复习了三个方法:Data() {},props:[''],methods:{}
这里用到了装饰器语法:
import {Component} from 'vue-property-decorator'
@Compontent 告诉TS export函数体里是Vue的一个组件,效果就是:type会自动被处理为 Data,selectType会自动被处理为methods。
@Prop(Number) xxx:number | undefined;
//Props是一个装饰器,他的作用就是告诉Vue,xxx不是Data是Prop.
//Number的作用是告诉Vue,XXX是一个Number
//xxx是一个属性名
//number | undefined是xxx的类型
小问题:使用官方文档给的提示根本就不能使用props,为什么呀? 最后选择了使用第三方提供的props
不过我发现了TS最大的好处(对我而言吧):
- 文档的自动提示更智能
- 如果我声明了一个类型,调用的时候如果出错TS会报警的。TS会检查你调用的这个方法是否可以真的调用
- TS是编译的时候进行报错,而JS是运行的时候进行报错.TS编译报错无法得到JS终端Error.
总结:怎么使用TS组件:
我们必须从vue-property-decorator里引入一个叫做Component这个装饰器。然后将装饰器修饰到Class上。Class可以声明Data和methods。也可以加上生命周期。
//1:用JS对象
export default{data,props,methods.created,...}
//2.用TS类,<script lang="ts">
@Component
export default class XXX extends Vue{
xxx:"string='hi';
@Prop(Number) xxx:number | undefined;
}
//3.用JS类
@Component
export defalut class XXX extends Vue{
xxx='hi'
}
NumberPad
注意:
- 不可以有两个小数点
- 注意0的位置(比如0可以在开头吗?)
其实事件里是没有点击事件的,点击事件其实是鼠标事件的一类。
使用的时发现TS提示我的target为空,这是我之前没有想到过的。经过提醒,强制给他添加一个类型。主要是因为Vue和TS的结合不够好。
notes
input的event是个什么事件呢?不过问题不大,编译之后就不见了。 重点!!! 如果你的代码里出现了
value="value"
@input="value = $event.target.value"
那么我们就可以把它简写成
:value="x"
@input="x = $event.target.value"
//等同于下面的
v-model="x"
tags
<script lang="ts">
import Vue from 'vue';
import {Component, Prop} from 'vue-property-decorator';
@Component
export default class Tags extends Vue {
@Prop() readonly dataSource: string[] | undefined;
selectedTags: string[] = [];
//判断选中状态
toggle(tag: string) {
const index = this.selectedTags.indexOf(tag);
if (index >= 0) {
this.selectedTags.splice(index, 1);
} else {
this.selectedTags.push(tag);
}
this.$emit('update:value', this.selectedTags);
}
//新增标签
create() {
const name = window.prompt('请输入标签名');
if (name === '') {
window.alert('标签名不能为空');
} else if (this.dataSource) {
this.$emit('update:dataSource',
[...this.dataSource, name]);
}
}
}
收集四个组件
(tags,notes,numberpad,types的Value值)
@watch ('child') onChildChanged(val:string,oldVal;string){}
watch是在某个东西发生变化的时候进行监听
使用.sync方法 其实四个组件整合这里我不是很熟悉,怎么说呢。用的并不好
第六天:使用LocalStorage
当用户点击OK的时候,将数据放在LocalStorage里。
- 监听record.amount的点击状态
- 重新监听submit事件
saveRecord(){
const record2 = JSON.parse(JSON.stringify(thisrecord));
this.recordList.push(record2);
}
@Watch(path:'recordList')
onRecordListChange(){
window.localStorage.setItem('recordList',JSON.stringify(this.recordList))
}
第七天:动态的获取tags
使用v-for去循环tags
MVC的所有数据操作都是由model自己控制的。
一开始需要fetch(),目的是为了加载数据。
将data放在tags里。
创建的时候注意判断标签名重复。
第九天:如何封装一个通用组件:
改造Notes.vue,让他成为通用组件。
一.数据从父组件传入
为了解耦,子组件本身就不能生成数据。即使生成了,也只能在组件内部运作,不能传递出去,下面是在一些较复杂的场景中,对props传递的参数加一些验证,也是方便如果是数据类型不符合可以直接抛出异常。
二.在父组件处理事件
比如某些子组件的click事件,避免高耦合,逻辑最好放在父组件中,子组件只是一个承载体。
三.slot的应用
现在有一个需求,在同一个子组件中,我在不同 的场景需要用到不同的按钮,那么在封装组件的时候就不用去写按钮,只用在合适的未知留一个slot,把按钮的位置留出来,然后再父组件中写入:
代码重构:使value从data变成了props
第十天:使用Vuex进行全局数据管理
小知识:使用Vue中的deep语法作为深度作用选择器,类似于Sass之类的预处理器无法正确解析 >>> 等语法,在这种情况下可以选择使用/deep/或者是::v-deep等操作符取而代之,两者皆为 >>> 的别名。意思是选择当前组件里层的组件
mutation:method
action:调用method
使用mixin优化代码