一.使用vite创建项目
不选择vue-cli脚手架,换成使用vite,vite最大特点就是快,不需要进行打包,热加载快 是一个通用的脚手架工具
这里出了一个问题,就是vetur不支持vue3,所以HelloWorld组件就不能正常使用,需要把它卸载换成
二.ESlint初步使用
安装配置eslint:
添加rules之后:
eslint.config.js:(检测有没有分号)
js
import globals from "globals";
import tseslint from "typescript-eslint";
/** @type {import('eslint').Linter.Config[]} */
export default [
{ files: ["**/*.{js,mjs,cjs,ts}"] },
{ languageOptions: { globals: globals.browser } },
...tseslint.configs.recommended,
{
rules: {
semi: 2
}
},
];
代码中也会有相应的提示:
extends字段:添加规则组
后期和vite结合,添加vue和typeScript的规则组
三.响应式API:ref、reactive
ref:
js
<script lang="ts">
import { defineComponent,ref } from 'vue';
export default defineComponent({
name:'APP',
setup()
{
const count=ref(0); //声明响应式对象
const increase=()=>{
count.value++; //这里要加上value
}
return {
count,
increase
}
}
})
</script>
<template>
<div>
<h1>{{ count }}</h1>
<button type="button" v-on:click="increase">increase</button>
<a href="https://vite.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
</template>
reactive:参数必须是一个对象
怎么把响应式对象和TS结合起来呢,使用泛型来定义ref的类型,value++之前进行判断
js
<script lang="ts">
import { defineComponent,ref,reactive} from 'vue';
export default defineComponent({
name:'APP',
setup()
{
const count=ref<string | number>(0); //声明响应式对象
const user=reactive({
name:'viking',
age:30,
})
const increase=()=>{
if(typeof count.value==='number')
count.value++; //这里要加上value
user.age++; //不用加value进行访问
}
return {
count,
increase,
user,
}
}
})
</script>
给reactive标记类型:
js
<script lang="ts">
import { defineComponent,ref,reactive} from 'vue';
interface person {
name:string,
age:number
}
export default defineComponent({
name:'APP',
setup()
{
const count=ref<string | number>(0); //声明响应式对象
const user:person = reactive({
name:'viking',
age:30,
})
const increase=()=>{
if(typeof count.value==='number')
count.value++; //这里要加上value
user.age++; //不用加value进行访问
}
return {
count,
increase,
user,
}
}
})
</script>
四.computed计算属性
js
<button type="button" :disabled="user.age<10">{{ user.age>=10 ?'可以参与':'不可以参与'}}</button>
如果要都写表达式的话,会使模板变得很复杂,所以就可以使用计算属性
js
const buttonStatus=computed(()=>{
return {
text:user.age>=10?'可以参加':'不可以参加',
disable:user.age<10
}
})
js
<button type="button" :disabled="buttonStatus.disable">{{ buttonStatus.text }}</button>
计算属性在数据更新的时候才会重新计算
五.watch监听器
js
watch(count,(newValue,oldValue)=>{
console.log('old',oldValue);
console.log('new',newValue);
document.title=`目前点击的数是${newValue}`
})
不能直接监听一个对象的属性,要添加在箭头函数返回值后面
js
watch(()=>user.age,(newValue,oldValue)=>{
console.log('old age',oldValue);
console.log('new age',newValue);
document.title=`目前点击的数是${newValue}`
})
或者直接传入一个参数
js
watch(user,(newValue,oldValue)=>{
console.log('old age',oldValue);
console.log('new age',newValue);
document.title=`目前点击的数是${newValue}`
})
立即监听执行器,加上 {immediate:true}
六.生命周期、模板引用
js
onMounted(()=>{
console.log('mounted');
})
onUpdated(()=>{
console.log('updated');
})
onMounted用得是最多的,加载完毕的时候进行一些操作,比如发送异步请求
模板引用
js
const headline=ref(null);
<h1 ref="headline">{{ count }}</h1>
//onmounted中:
onMounted(()=>{
console.log('mounted',headline.value);
})
可以访问到dom节点:
使用TS的联合类型定义:(组件未加载完毕的时候可能是null)
js
const headline=ref<null|HTMLElement>(null);
js
onMounted(()=>{
if(headline.value)
console.log('mounted',headline.value);
})
七.组件基础-属性Props
MyFile组件:
js
<template>
<div class="profile-component"></div>
<h1>name:{{ name }}</h1>
<h1>age:{{ age }}</h1>
<h1>doubleAge:{{ doubleAge }}</h1>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
export default defineComponent ({
name:'MyFile',
props:{
name:{
type:String,
required:true
},
age:{
type:Number,
default:30
}
},
setup(props) {
const doubleAge=computed(()=>props.age*2)
return{
doubleAge
}
},
})
</script>
<style scoped>
</style>
在App.vue中给它传值:
js
<MyFile name="lyt"/>
把属性修改成一个对象:使用TS来标注类型(PropType)
js
<template>
<div class="profile-component"></div>
<h1>name:{{ user.name }}</h1>
<h1>age:{{ user.age }}</h1>
<h1>doubleAge:{{ doubleAge }}</h1>
</template>
<script lang="ts">
import type { PropType } from 'vue';
import { computed, defineComponent} from 'vue';
interface Person{
name:string,
age:number
}
export default defineComponent ({
name:'MyFile',
props:{
user:{
type:Object as PropType<Person>,
required:true
}
},
setup(props) {
const doubleAge=computed(()=>props.user.age*2)
return {
doubleAge
}
},
})
</script>
<style scoped>
</style>
在App.vue中使用要进行改变:
js
<MyFile :user="user"/>
八.组件自定义事件
子组件显示和隐藏功能:emit中添加了change事件,把isHidden的value传给父组件
js
<template>
<div class="profile-component"></div>
<h1>name:{{ user.name }}</h1>
<h1 v-if="!isHidden">age:{{ user.age }}</h1>
<h1 v-if="!isHidden">doubleAge:{{ doubleAge }}</h1>
<button type="button" @click="toggleHide">{{ isHidden?'显示':'隐藏' }}</button>
</template>
<script lang="ts">
import type { PropType } from 'vue';
import { computed, defineComponent,ref} from 'vue';
interface Person{
name:string,
age:number
}
export default defineComponent ({
name:'MyFile',
props:{
user:{
type:Object as PropType<Person>,
required:true
}
},
emits:['change'],
setup(props,ctx) {
const isHidden=ref(false);
const doubleAge=computed(()=>props.user.age*2)
const toggleHide=()=>{
isHidden.value=!isHidden.value
ctx.emit('change',isHidden.value)
}
return {
doubleAge,
isHidden,
toggleHide
}
},
})
</script>
<style scoped>
</style>
App.vue中写相应的事件:获取到子组件的状态
js
const onChange=(hidden:boolean)=>{
document.title=hidden?'隐藏':'显示'
}
<MyFile :user="user" @change="onChange"/>