全局组件 Nav 导航栏 怎么设置比较人性化?
1.加在页面固定位置→后续想设置导航栏隐藏挨个页面隐藏就很麻烦→✖
2.单独开一个代码页面写一个导航栏→那个页面用就引用→每次引用都声明有点麻烦……?→做成全局变量一次性引用✔
路由配置:
路由会逐次的去配对,不在路由表里的统一归纳到 “*” 所以添加一条路由
{
path:'*',
component:Notfound
}
这个页面写404报错,然后设置返回主页面的方法
返回页面:
1.<router-link to="/">
2.<a href="#/">
效果一样,任意选择
<template>
<div>
<div>404</div>
<div>
<router-link to="/"> 返回首页</router-link>
</div>
</div>
</template>
</template>这个标签只能有一个主<div>,所以写一个主的把这两个包进去,不然会报错
CSS定位实现
fixed还是flex? fixed由于三改过,各个浏览器支持的版本不一,实现移动端开发是很难的。所以选用flex,方便后期维护
<style lang="scss" scoped>
.nav{border:1px solid red;}
</style>
scoped:会自动生成一串字符,添加到<template>中的<nav>中,这样 .nav只会影响到当前<template>中的nav
总结:能加scoped就加吧,这样不会让自己的div class 和其他的页面起冲突
flex-grow:1;
1:尽可能的高,类似于占比百分百
overflow: auto;
如果内容被修剪,会出现滚动条
vue插槽 <slot>:重复的东西写组件传递,不重复的东西slot插槽插进去
在vue引入svg:把 svg变成symbol,再把symbol外面套上一层svg 再引用
vue.config代码:
const path = require('path')
const { config } = require('process')
module.exports = {
lintOnSave: false,
chainWebpack: config => {
const dir = path.resolve(__dirname, 'src/assets/icons')
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').use(require('svg-sprite-loader/plugin'), [{ plainSprite: true }])
config.module.rule('svg').exclude.add(dir)//其他SVG排除loader目录
}
}
svgo o:优化的单词缩写
<label class="notes">
<span class="name">备注</span>
<input type="text" placeholder="在这里输入备注" />
</label>
用labal把Input包起来就可以直接建立二者的关联,不用写那么多了
一个前端文件一般要少于150行,多了的话就拆分成模块吧。这样省内存
placeholder语法
%x{
&::after{
content: '';
clear: both;
display: block;
}
}
使用的时候
buttons{
@extend %x;}
相当于每次编译的时候,把buttons选择器每次复制过去,然后编译。所有选择器都会出现在x的位置
box-shadow inset:内阴影
box-shadow: inset 0 -2px 5px -5px fade-out( #D47926, 0.5) ;
0:左右不变 -2px:阴影向上移动2px 5px:宽度为5px -5px:阴影向内推进5px
TS的第一次使用
有两个按钮,用JS控制切换,这里我把JS改成了TS
具体踩坑和Bug修复以及原理请看我的这一篇博客,这里不再赘述//www.greatytc.com/p/ac010ace611a
TS是不会使用构造选项的,赋值语句会自动变成实例的属性,实例的属性会默认的变成data,所以直接写 type=' '
<script lang="ts">
import Vue from 'vue'
import {Component} from 'vue-property-decorator';
@Component
export default class Types extends Vue {
type ='-'//'-'表示支出,'+'表示收入
selectType(type:string) {
///type只能是‘-’或者“+”
if (type !== "-" && type !== "+") {
throw new Error("type is unknow");
}
this.type = type;
}
}
先从vue-property-decoratoryin'ru'y引入一个叫做Component的装饰器,然后把装饰器修饰到class上,然后我的class可以声明data和methods。这里面的data就是type ='-'
想在ts里面加上prop属性,查了文档之后得到了如下简化后的代码
@Prop(Number) xxx:number|undefined
我在另一个文件里引用了xxx
<Types :xxx=345678 />
有报错,然后加上了判断语句报错消失
mounted(){
if(this.xxx === undefined){
console.log('no xxx')
}else{
console.log(this.xxx.toString());
}
}
总结下怎么用TS声明Vue组件。
首先要引入Component和Prop,从vue-property-decorator这个库里面引用。然后要声明一个类Type,在这个类上面必须写@Component。如果要声明data,赋值语句会自动变成实例的属性,实例的属性会默认的变成data,所以直接写 .声明methods也直接写就好了,和js一样。声明Prop类型按照官方文档写@Prop(Number) xxx:number|undefined在Prop的后面( )里写一个运行时的类型,在:后面写上编译时的类型
不一定所有元素都有内容,图就没有,这个BUG可以用强制指定类型 as
event.target as HTMLButtonElement 强制类型转换
如果在代码里写了
:value = "x"
@input="x=$event.target.value"
那么可以替换成
window.localStorage 怎么用
这是错误写法
recordList:Record[ ]=
window.localStorage.getItem('localStorageKeyName')
因为我不能将字符串赋值给一个数组,想要字符串变成数组,用json
recordList:Record[ ]=
JSON.parse(window.localStorage.getItem('localStorageKeyName'))
这么写,万一数组是空怎么办?null不是数组啊。所以再给他一个空的字符串
recordList:Record[ ]=
JSON.parse(window.localStorage.getItem('localStorageKeyName')||'[]')
数据迁移是什么
深拷贝:先把对象变成一个字符串,然后再把字符串变成对象,这样就拥有完全一样的所有属性,但是是一个新的对象
把js后缀改成ts,把所有报错都改掉。
iconfont 小技巧,编辑 SVG
创建标签成功要返回什么?
create(name:string) {
this.data.push(name);
this.save();
if (this.data.indexOf(name) >= 0) {
return ?
}
return ?
}
如果返回的是 success 和 !success ,但是用户并不知道失败的原因是什么。
如果直接报错,报错时写出原因。那尝试下try和catch,然后打印出错误
if (name) {
try{
tagListmodel.create(name)
}catch(error){
console.log(error)
}
报错提示:
发现错误是duplicated,如果改成当错误信息是duplicated就弹出一个alert提示用户是标签名重复呐?于是代码改成
if (name) {
try{
tagListmodel.create(name)
}catch(error){
if(error.message==='duplicated'){
window.alert('标签名重复')
}
create:(name:string) => number
create(name:string) {
this.data.push(name);
this.save();
if (this.data.indexOf(name) >= 0) {
return ture;
}
return false;
}
可行,但是不够好,返回值是true或者false不知道返回的具体错误是什么,那如果把返回值改成数字呐?每个数字代表不同的错误,那试一下成功返回0,失败返回1
create:(name:string) => number
create(name:string) {
this.data.push(name);
this.save();
if (this.data.indexOf(name) >= 0) {
return 1;
}
return 0;
}
确实可以,可是时间长了,0,1分别代表的意义会被遗忘,那尝试返回字符串吧
create:(name:string) => string
create(name:string) {
this.data.push(name);
this.save();
if (this.data.indexOf(name) >= 0) {
return 'duplicated';
}
return 'success';
}
如果是多人团队合作,其他的合作者不知道我的返回值只有success和duplicated两种,我有什么办法让他知道呢?
改前面的声明,声明类型的时候直接写返回值
create:(name:string) => 'success'|'duplicated'//联合类型
联合类型:是字符串的子类型,不属于7个数据类型,类似于枚举法
path:'/labels/edit/:id',
:id 表示是我后面会有一个字符串,但是我现在不知道是多少,拿来站位
一般来说,和路由相关用route,和路由器相关用router
custom.d.ts 怎么用
让一个变量在所有文件都可以用它。d的定义的意思, ts发现文件以** .d.ts** 结尾,就知道这个文件是声明,声明变量的。
把希望在全局使用的变量声明写在里面
@click.native 怎么用?
我知道你这个组件没有click属性,但是你对应的组件有这个click属性,所以对应的组件是可以接受这个click的
Vue Router 怎么用
this.$route this为什么有 $route 这个属性,因为安装了一个叫做Vue router 的库,里面的声明是这样的:
declare module 'vue/types/vue' {
interface Vue {
$router: VueRouter
$route: Route
}
}
用来收集路径的信息
数据不同步问题:两个页面分别写了fetch()获取到用户更改的对象,但是页面之间内无法交换数据
解决:在更高一级上面写fetch() 例如main页面 例如app页面。
全局数据管理/全局状态管理是啥
全局状态管理(也叫全局数据管理)的好处是什么?
解耦:将所有数据相关的逻辑放入 store(也就是 MVC 中的 Model,换了个名字而已)
数据读写更方便:任何组件不管在哪里,都可以直接读写数据
控制力更强:组件对数据的读写只能使用 store 提供的 API 进行(当然也不排除有猪队友直接对 tagList 和 recordList 进行 push 等操作,这是没有办法禁止的)
store和model都是仓库,模板,把model写到store里一起调用吧
this根据函数确定的。函数!在export default 里面返回的是一个key 不是函数,所以调用不了
在定义一个对象的过程中,没有办法使用对象,因为还没定义完
store 怎么模块化
在 store 里const 一个对象 ,然后把model里的模块,写到新对象里,然后exprot default 对象 把他暴露出去
如何封装
把tags,record里的recordListmodel封装成全局变量。也就是window.xxxx()
全局变量太多
过于依赖window(node.js里没有window这个对象)
变量太多解决方法:把所有的东西挂到stroe身上。在custom.d.ts 里声明一个window里的变量,叫store 把刚刚声明的全局变量都写到里面,这样变量依赖的就是store了
依赖window解决:不要window。新建一个index2.ts。把store写在里面成为一个单独的对象,不依赖window
createTag 创建一个tag 看有没有重复 重复了alert "标签重复" return duplicated
如果没有重复 运行创建过程 return success
this.recordList&&this.recordList.push(record2);///可调换成this.record?.push(record2)
? 写法。(可选链)最新版本的vs code 和TS版本>3.7.5
@Prop({required:true}) dataSource!: string[];
require:true 必须传一个数组,不传就会报错
Vuex重构EditLable页面 里面有获取tag这个操作嘛,之前写的store是直接调用 store.findtag(this.$route,param.id) 因为改写成vuex,mutation读写数据,只能调用,不能return 于是改写 this.tag=this.$store.commit('findtag',this.route.param.id) 结果标红了 不能把viod赋值给tag 于是去查了commit的返回值 index.d.ts发现 store.commit 没有返回值,还真是void,那就说明没办法通过commit获取到数据啊,那在store上面 填一个currentTag ,要声明类型,不好声明我给了个undefined 感觉写了没啥意义 然后写了个type 里面的currentTag?:Tag 可以是Tag可以是Undefined 没有报错 那我就想办法得到currentTag 在computed里写tag()
{ return this.$store.state.currentTag} 取到了值 取到值之后还得让他改嘛 要让他赋值 肯定是要调用一个commit 然后我又写了一个 setcurrentTag 当调用这个函数的时候,值会修改。
给我一个id我就会让currentTag=tag,然后出现 新的报错。tag不存在????
我看了下之前写的代码,发现computed里面写过的变量,没有在export default class 里用过。试了下其他的变量也都是标红的,是不是TS和VUE不可以这么结合使用?我去翻了Vue-property-decorator文档,结果,没有相关答案!然后我又去翻了原生文档 Vue class comnonent,发现人家用了原生自带的get和set函数
这么一看确实简洁多了,我不用compouted了,直接get tag(){ return this,$store.state.currentTag} 成功了,然后发现,之前所有的computed都是错的。大改吧
mutations:里面用的函数只能有一个变量,有2个就会报错,若果有两个的话,写到object里 再调用
updateTag(state, object:{ id: string, name: string }) {
const id =object.id
const name=object.name}
为了迎合Vuex的喜好,我还是把object改成payload吧
deep语法
引入组件之后在CSS里写上 scoped 可以防止其他的组件被污染 如果想设置引入组件的属性,因为有了scoped的保护,无法更改内容,解决办法 deep语法
<style scoped lang="scss">
.x /deep/ li{ /////.x 深入到里面的组件 li 不看外面的组件,只看里面的
border:1px solid red.
}
</style>
如果出现了sass 报错,那可能是sass之类的预处理器无法正确解析
可以改成 ::v-deep 取代
ES6 如果你的key里面有变量,可以用中括号 [ ] 把他们包起来
:value.sync=“ ”里的值必须是变量
object.freeze 可以保证里面的变量不可修改
想做成这样的,2个都用了Tab组件,高度做变更,CSS优先级靠前的会被使用,有两个办法 一个是把第二个的CSS写的更精细 li..interval-tabs-item 这种,缺点就是没办法保证里面的是li标签 还有可能是div
另一个是 在CSS里 改成同级的
.tabs{
&-item{
}}
在li标签上写 class="tabs-item"
两种都有可以 第2种更好一点?
方法3:用JS
在Tabs组件里 声明prop (String,'64px') height!:string 然后在用属性或者CSS写另一个高度
json支持的类型 object array string number "ture" "false" "null" 没有Date
[ ]+String=[{ , }, { , },{ , }]
用计算属性
在TS里 this.$store.state.xxx
数据需要排序!不排序不能保证后插入的数据可以按照正确的顺序显示,所以数据一定是一个有序数组!
sort()会改变数组本身
foreach是没有返回值的map,
$emit的Bug ,$emit无法指定第二个参数的类型
组件{构造选项+装饰器}
mixin 节约多次代码的重复书写,写一次,继承下就可以了
conputed 获取数据,可以自动根据依赖缓存,节省技术按次数
TS里面需要写getter语法
Watch ,prop ,sync,v-model装饰器写法
《slot》插槽 具名
eslint
localStorage 只可以存5到10M
表驱动编程 :class{key: value:}
模块化思想 store
重构技巧 多写几遍
Vue Router Hash/history模式 是SPA模式,单一页面应用
Vuex window.store