VUE+TS 方法整理
内容《Vue.js 权威指南》GIT源码篇 -双向绑定1、keep-alive -生命周期刷新操作1、keep-alive -生命周期刷新操作简介: 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。适用场景:https://www.jb51.net/article/131110.htmbeforeRouteEnter 总会触发:不使用 keep-alive 时,before
实操
面试 | 【1】 thWinterSun -GIT面试!!! 【2】 FrankKai-GIT面试!!! |
---|---|
【1】9 年小厂老前端的年终总结 | 【2】三十七个常见Vue面试题 【3】 关于 let 暂时性死区 |
-
1、
keep-alive
-生命周期刷新操作; -
2、
window.scrollTo()
、offsetTop
滚动条操作;
-
获取
JSON.parse()
,转为一个对象。将URL解析成对象的形式; -
设置
JSON.stringify()
,转为 JSON 字符串。将对象 序列化成URL的形式,以&进行拼接; -
JSON.parse(JSON.strightfy(this.value)) 拷贝一层;
-
this.$refs[formName].validate()
: - 此时表单内的 dom 还没有加载完成就执行了,从而报错。this.$nextTick(()=>{})
- 等 form 表单的 dom渲染 完在执行;
TypeScript 特点:
TypeScript 是一种有微软开发的自由和开源的编程语言,是JavaScript的超集。
- 1、类型批注和编译时的类型检查(声明变量 var a:number) ;2、强类型语言;3、面向对象;4、类class;5、接口(Interface),类型别名(type); 6、泛型(< T>);7、lambda 函数;
【1】 Type 和 Interface 都可以描述一个对象或者函数
,选用时机?
- Interface 用来描述 对象(object) 的形状 或者对 类(class) 的行为 进行抽象。
- 在定义公共 API 时(比如编辑一个库)使用 interface,这样可以方便使用者继承接口;
- 在定义组件属性(Props)和 状态(State)时,建议使用 type,因为 type的约束性更强;
Interface 和 Type 在ts中是两个不同的概念,但 type 和 interface 最大的区别是
: type 类型不能二次编辑,而 interface 可以随时扩展;
- 接口 Interface属性: 可选属性
在属性后边加?
- 含义是该属性可以不存在; - Type 声明可以定义联合类型,基本类型等多种类型,而 interface 只能定义对象类型
【2】泛型
// 【1】泛型约束
// 泛型 T 不一定包含属性 length,所以编译的时候报错了
function getLength<T>(arg:T):T {
console.log(arg.length) // error: Property 'length' does not exist on type 'T'
return arg;
}
// 【2】使用 extends 约束泛型 <T> 必须符合 Ilength 的形状,也就是必须包含 length 属性
interface Ilength {
length: number
}
// 泛型约束
function getLength<T extends Ilength>(arg:T):T {
console.log(arg.length)
return arg;
}
getLength('abcd') // 4
=========================
// 举个栗子
function identity<T>(arg: T): T {
return arg;
}
// 这里的 T 为类型变量,表示类型而不是值。
// 这里 T 帮助ts捕捉用户输入的类型,之后就可以使用这个类型。使用T当做返回值类型,这样可以知道传入值和返回值类型是相同的。
// 这样就可以跟踪函数里使用的类型的信息。这个就叫做泛型。可以适用于多个类型,不会丢失信息。保持准确性,传入数值类型并返回数值类型。
// 使用泛型函数
// 1. 传入所有参数,包含类型参数
let output = identity<string>('mystring');
// 2. 利用类型推论 -- 即编译器会根据传入的参数自动的帮助我们确定T的类型
let output = identity('mystring');
// 类型推论帮助我们保持代码精简和高可读性。如果编译器不能够自动地推断出类型的话,只能像上面那样明确的传入T的类型,在一些复杂的情况下,这是可能出现的。
// 泛型接口
interface genFn<T> {
( arg : T ) : T;
};
let ide : genFn<number> = identity;
// 泛型类
class Gen <T> {
zero : T;
add : ( x : T, y : T ) => T;
}
let gen = new Gen<Number>();
//泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。
// 泛型约束
// 利用接口来描述约束条件,然后使用这个接口和extends关键字实现约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
// 这时的泛型函数被定义了约束,因此它不再是适用于任何类型。
【3】 实用工具类型:
- 1、
Partial<T>
— 将 T 中所有属性转换为可选属性,返回的类型可以是 T 的任意子集。 - 2、
Pick<T,K>
— 通过在T中抽取一组属性K构建一个新类型。
VUE - @Component / @Prop
vue-property-decorator 装饰器的使用。
<script lang="ts">
import { Component, Vue, Prop, Emit, Watch } from 'vue-property-decorator';
import { UserInfo, NavListItem } from "@/types/index";
export interface NavListItem {
index: string;
path: string;
name: string;
}
// HTTP
export interface ResponseData {
code: number;
data?: any;
message: string;
}
@Component({ //Component组件装饰器,用于增加一些全局的配置,比如过滤器filters
components: {
//components里面放一些全局的组件,引入子组件后写在这,跟vue中的components一样
},
})
export default class Home extends Vue {
@Prop({ default: 'default value' }) readonly propB!: string; // Prop, ! -值不能为空
@Prop(String)
propA:string;
@Prop([String,Number])
propB:string|number;
@Watch('child', { immediate: true, deep: true }) // 监听器
onChildChanged(val: string, oldVal: string) {} // 监听器相应方法
private articlesList: Array<object> = [];
private list: Array<NavListItem> = []; // 适合写死的
mounted(): void { // 钩子函数
this.onChildChanged(this.$route, this.$route);
}
// 父: @cancel="onHandleCancel"
@Emit()
private cancel(): boolean {
return false;
}
private handleOAuth(): void {
// 保存授权前的页面链接内容
let preventHistory: object = {
name: this.$route.name,
query: this.$route.query
};
window.sessionStorage.preventHistory = JSON.stringify(preventHistory);
// window.location.href = 'https://github.com/login/oauth/authorize?client_id=6de90ab270aea2bdb01c&redirect_uri=http://biaochenxuying.cn/login'
window.location.href = `${config.oauth_uri}?client_id=${config.client_id}&redirect_uri=${config.redirect_uri}`;
}
}
</script>
@Provide
<script lang="ts">
import { Provide, Vue } from 'vue-property-decorator';
export default class Home extends Vue {
@Provide() private name: string = 'weipingping'; //定制属性,替换data,正常情况下直接使用
//private 修饰的属性或者方法是私有的,只在此类中有效
//public 修饰的属性或者方法是公有的,任何组件都可以访问到
//protected 修饰的属性或者方法是私有的,但它的子组件可以访问到
}
</script>
@Emit
<script lang="ts">
import { Emit, Vue } from 'vue-property-decorator';
export default class Home extends Vue {
//Emit 给父组件传值
//方式一
private add(): void{
@Emit("add","传递的参数")
}
//方式二
@Emit ("add","传递的参数")
private add(): void{
console.log("这个方法运行完成后触发Emit")
}
}
</script>
计算属性
<script lang="ts">
import { Component, Vue, Provide } from 'vue-property-decorator';
@Component({
components: {},
})
export default class Home extends Vue {
@Provide() private one: number = 5;
@Provide() private two: number = 6;
// 计算属性直接前面加get就可以了
get allNum() {
return this.one + this.two;
}
}
</script>
var arr = [[1,1,1],[2,2,2],[3,3,3],[4,4,4],[5,5,5]]
console.log(arr)
var newArray = arr[0].map(function(col, i) {
console.log(i)
return arr.map(function(row) {
console.log(row)
return row[i];
})
});
console.log(newArray) // [[1,2,3,4,5],[1,2,3,4,5]]
1、keep-alive
-生命周期刷新操作
简介: 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
适用场景: https://www.jb51.net/article/131110.htm
beforeRouteEnter 总会触发:
-
不使用 keep-alive 时,
beforeRouteEnter --> created --> mounted --> destroyed (组件被停用时) -
使用 keep-alive 时,
beforeRouteEnter --> created --> mounted -->activated
(组件被激活时)–> deactivated
2、window.scrollTo()
、offsetTop
滚动条操作
<template>
<!-- 实时资讯 -->
<main class="item-content" :ref="myRefThree">
<RumorList :rumorListData="rumorListData"/>
</main>
<!-- 疫情科普 -->
<main class="item-content" ref="myRefFour">
<WikiList :wikiListData="wikiListData"/>
</main>
</template>
export default {
setup() {
onMounted(() => {
// 1、获取 arrScrollDom 数组列表
stateData.arrScrollDom = document.getElementsByClassName("item-content")
// 2、获取滚动条
window.addEventListener('scroll', handleScroll)
})
// 3、ref 获取DOM元素,setRefOne -获取后的值
let setRefOne = ''
let setRefTwo = ''
const myRefOne = el => { setRefOne = el }
const myRefTwo = el => { setRefTwo = el }
// 3.5、标题TAB点击-获取滚动条位置
const onTitleTopClick = (id) => {
let dom
if (id == 1) dom = setRefOne.offsetTop
else if (id == 2) dom = setRefTwo.offsetTop
else if (id == 3) dom = setRefThree.offsetTop
else dom = setRefFour.offsetTop
window.scrollTo(0, dom) // 滚动条位置
stateData.titleTopId = id
}
// 4、标题TAB滚动条位置
const handleScroll = () => {
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
// 获取 arrScrollDom 数组长度
let arrScrollDomLength = stateData.arrScrollDom.length
stateData.headerFixed = scrollTop > ctx.offsetTop // 返回布尔值
for (let i = 0; i < arrScrollDomLength; i++) {
// 因为下面使用到了i+1,所以需要把最后一个分离出来判断
if (stateData.arrScrollDom[arrScrollDomLength-1].offsetTop-scrollTop > 80) {
if (stateData.arrScrollDom[i].offsetTop-scrollTop <= 80 && stateData.arrScrollDom[i+1].offsetTop-scrollTop > 80) {
stateData.titleTopId = i + 1 // 更新头部标题的 id(选中的)
}
} else {
stateData.titleTopId = arrScrollDomLength
}
}
}
// 页面离开销毁
onUnmounted(() => {
// 5、销毁 handleScroll 事件
window.removeEventListener('scroll', handleScroll);
})
return {
...toRefs(stateData),
myRefOne,
myRefTwo,
onTitleTopClick,
handleScroll,
}
}
}
更多推荐
所有评论(0)