vue+ts (1)

vue3简介

简单效果

创建vue3工程

执行:

npm create vue@latest

初始化:
在这里插入图片描述
目录介绍:
在这里插入图片描述
其中 env.d.ts的作用是 让ts认识它不认识的东西,如(txt,jpg)

在这里插入图片描述

在这里插入图片描述

注意:

1、vue3 运行npm create vue@latest 和 npm init vue@latest 执行速度慢的问题

在这里插入图片描述
解决:
1、查看npm代理
npm config get registry
2、更换npm镜像
npm config set registry=https://registry.npmmirror.com
3、查看npm代理
npm config get registry
修改后:
在这里插入图片描述

2、项目中没有node_modules:

安装所有依赖 npm i

编写App组件

插件安装:

在这里插入图片描述

/src/main.ts文件解释:

在这里插入图片描述

根组件 App.vue结构:
在这里插入图片描述
效果:
在这里插入图片描述
App.vue代码:

<template>
    <br>
    helloword
    <!-- html --> 
</template>
<script lang="ts">
//JS或TS
export default {
    name: 'App', //组件名
    }
</script>

<style scoped>
/* 样式 */
</style>


API

Setup

  setup(){
        //setup函数中的this是undeinfined
        //data
        
        let name = 'zs'//此时的name不是响应式的
        let age = 18//此时的age不是响应式的
        let tel= '13888888888'//此时的tel不是响应式的

1、返回对象


<template>
    <div>
        <h1>{{name}}</h1>
        <h1>{{age}}</h1>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="showTel">显示电话</button>
        
    </div>
</template>
<script lang="ts">

export default {
    name: 'Person',
    // data() {
    //     return {
    //         // 数据
    //         name: '张三',
    //         age : 18,
    //         tel: '13888888888',
    //     }
    // },
    // methods: {
    //     // 方法
    //     changeName(){
    //         this.name = '李四';

    //     },
    //     changeAge(){
    //         this.age+=1;
    //     },
    //     showTel(){
    //         alert(this.tel)
    //     },

    // },
    // computed: {
    //     // 计算属性
    // },
    // mounted() {
    //     // 页面加载完成后执行
    // },
    setup(){
        //setup函数中的this是undeinfined
        //data
        
        let name = 'zs'//此时的name不是响应式的
        let age = 18//此时的age不是响应式的
        let tel= '13888888888'//此时的tel不是响应式的


        function changeName() {
            name='zss'
        }
        function changeAge() {
            age +=1
        }
        function showTel() {
            alert(tel)
        }
        // 将数据、方法交出去,模板中才可以使用
         return {name,age,changeName,changeAge,showTel}

     
        
    }
}
</script>

效果图:
在这里插入图片描述

2、返回函数

export default {
    name: 'Person',
    setup(){
        //setup函数中的this是undeinfined
        //data
        
        let name = 'zs'//此时的name不是响应式的
        let age = 18//此时的age不是响应式的
        let tel= '13888888888'//此时的tel不是响应式的


        function changeName() {
            name='zss'
        }
        function changeAge() {
            age +=1
        }
        function showTel() {
            alert(tel)
        }
       
        return function () {
            return "haha"
        }//简写 return ()=> 'haha'
        
    }
   

效果图:
在这里插入图片描述
面试题:
问:Vue3中的setup和正常写的data、methods有什么关系?
答:

3、语法糖

  • 3.1

在这里插入图片描述效果:
在这里插入图片描述

  • 3.2

安装插件:npm i vite-plugin-vue-setup-extend -D
修改vite.config 文件==》引入,并引用插件
在这里插入图片描述

支持这么写:

<script lang="ts" setup name="Person111">
   let a =666
</script>

ref 创建基本类型的响应式数据

  • 作用:定义响应式变量
  • 语法:let xxx = ref(初始值)
  • 返回值:一个RefImpl的实例对象,简称 ref 对象或 ref
    ,ref的对象value属性是响应式的
  • 注意点:
    JS 中操作数据需要xxx.value ,但模板中不需要.value直接使用即可
    对于let xxx = ref(‘zs’)来说,name不是响应式的,name.value是响应式的

响应式


<template>
    <div>
        <h1>{{name}}</h1>
        <h1>{{age}}</h1>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="showTel">显示电话</button>
        
    </div>
</template>


<script lang="ts" setup name="Person">
		import { ref } from "vue"

        //ref 响应式
        let name = ref('zs')//此时的name不是响应式的
        let age = ref(18)//此时的age不是响应式的
        let tel= '13888888888'//此时的tel不是响应式的


        function changeName() {
            name.value='zss'
        }
        function changeAge() {
            age.value +=1
        }
        function showTel() {
            alert(tel)
        }
    
</script>

效果:
在这里插入图片描述

reactive 创建_对象类型的响应式数据

<template>
    <div>
        <h1>Car</h1>
        <p>品牌:{{car.brand}}</p>
        <p>颜色:{{car.color}}</p>
        <p>价格:{{car.price}}</p>
        <p>库存:{{car.stock}}</p>
        <p>销量:{{car.sales}}</p>
        <p>评分:{{car.score}}</p>
        <button @click="changePrice">修改价格</button>
    </div>
</template>

<script lang="ts">
</script>
<script lang="ts" setup name="Car">
	import { reactive } from 'vue';
	//data
    let car =reactive( {
        brand: '奔驰',
        color: '黑色',
        price: 1000000,
        stock: 100,
        sales: 10000,
        score: 5,
    })

    function changePrice() {
        car.price += 200;
    }
</script>

效果:
在这里插入图片描述
产生的对象:
在这里插入图片描述

ref vs reactive

  • 宏观角度
1、ref 用来定义:基本类型数据、对象类型数据
2、reactive 用来定义:对象类型数据
  • 区别
1、ref 创建的变量必须使用 .value (可以使用volar插件自动添加 .value)
2、reactive 重新分配一个新对象,会失去响应式(可以用Object.assign 去整体替换)
  • 使用原则
1、若需要一个基本类型的响应式数据,必须使用ref
2、若需要一个响应式对象,层级不深,ref 和 reactive 都可
3、若需要一个响应式对象,层级较深,推荐使用 reactive

toRefs and toRef

  • 作用:将一个响应式对象中的每一个属性,转换成ref对象
  • 备注:toRefs 和 toRef 功能一致,但 toRefs 可以批量转换
  • 语法:
<template>
    <div>
        <h1>Person2</h1>
        <p>姓名:{{Person2.name}}</p>
        <p>年龄:{{Person2.age}}</p>
        <p>电话:{{Person2.tel}}</p>
        <button @click="changeName">修改姓名</button>
        <button @click="changeAge">修改年龄</button>
        </div>
</template>
<script>

</script>

<script lang="ts" setup name="Person2">

import { toRefs,reactive,toRef} from 'vue';
//数据
let Person2 = reactive({
    name: 'zs',
    age: 18,
    tel: '13888888888',
});


let {name,age,tel} = toRefs(Person2);
let n1 = toRef(Person2,'name');
console.log(n1.value);
//方法


function changeName() {
    name.value += '~';

}

function changeAge() {
    age.value += 1;
}
</script>


计算属性

<template>
    <div>
        <h1>Person</h1>
        <p>姓:<input type="text" v-model="firstName"/></p>
        <p>名:<input type="text" v-model="lastName"/></p>
        <p>全名:{{fullName}}</p>
        <button @click="changeFullName">修改全名</button>
        </div>
</template>

<script lang="ts" setup name="compute">
import { ref,computed } from 'vue';
let firstName = ref('张');
let lastName = ref('三');
//定义的fullName 是一个计算属性,只可读,不可修改
/*let fullName =computed(()=>{
    return firstName.value.slice(0,1).toUpperCase()+firstName.value.slice(1) + lastName.value;
})
*/

//定义的fullName 是一个计算属性,可读可修改
let fullName =computed({
    get(){
        return firstName.value.slice(0,1).toUpperCase()+firstName.value.slice(1) + lastName.value;
    },
    set(value){
        let names = value.split('-');
        firstName.value = names[0];
        lastName.value = names[1];}})
function changeFullName() {
    console.log(fullName.value);
    fullName.value = 'li-si';
}
</script>
<style scoped>

</style>



在这里插入图片描述

在这里插入图片描述

watch

  • 作用:监视数据的变化(和Vue2中的watch作用一致)
  • 特点:vue3中的watch只能监视以下四种数据:

1、ref 定义的数据
2、reative定义的数据
3、函数返回一个值
4、一个包含上述内容的数组

在vue3中使用watch通常遇到以下几种情况:
情况一:监视ref 定义的【基本类型】数据:直接写数据名即可,监视的是其value值的改变

<template>
    <div>
        <h2>当前求和为:{{ sum }}</h2>
        <button @click="changeSum">+1</button>        
    </div>
</template>
<script lang="ts" setup name="Watch">
import { ref,computed ,watch} from 'vue';
        let sum = ref(0)
        //方法
        function changeSum() {
            sum.value += 1;
        }
        //watch
        //watch(谁?回调函数)
       const stopWatch= watch(sum,(newValue,oldValue)=>{
            console.log('sum的值发生了变化',newValue,oldValue);
            //解除监视
            if(newValue>=10){
                stopWatch()
            }
        
        })
        
</script>
<style scoped>

</style>

情况二:监视ref定义的【基本类型】数据:直接写数据名,监视的是对象的【地址值】,若想监视对象内部的数据,要手动开启深度监视

注意
1、若修改的是ref定义的对象中的属性,newValue和oldValue 都是新值,因为它们都是同一个对象
2、若修改整个ref定义的对象,newValue是新值,oldValue 是旧值,因为不是一个对象了。

<template>
 <div>
  <h1>Person</h1>
  <h2>姓名:{{Person.name}}</h2>
  <h2>年龄:{{Person.age}}</h2>
  <h2>tel:{{Person.tel}}</h2>
  <button @click="changeName">修改姓名</button>
  <button @click="changeAge">修改年龄</button>
  <button @click="changePerson">修改Person</button>
 </div>
</template>
<script lang="ts" setup name="Watch">
import { ref,computed ,watch} from 'vue';
  let Person = ref({
    name: 'zs',
    age: 18,
    tel: '13888888888',
  });

  function changeName() {
    Person.value.name += '~';
  }
  function changeAge() {
    Person.value.age += 1;
  }
  function changePerson() {
    Person.value = {
      name: 'ls',
      age: 20,
      tel: '13888888888',
    };
  }
  //watch
  //watch(谁?回调函数)
  //watch第一个参数:被监视的数据
  //watch第二个参数:回调函数
  //watch第三个参数:配置项 (immediate:立即监视  deep:深度监视  等等)
  watch(Person,(newValue,oldValue)=>{
    console.log('Person的值发生了变化',newValue,oldValue);
  },{
    immediate:true,//立即监视
    deep:true,//深度监视
  })
</script>
<style scoped>

</style>

情况三:监视reactive 定义的对象类型、数据、且默认开启了深度监视

<template>
 <div>
  <h1>Person</h1>
  <h2>姓名:{{Person.name}}</h2>
  <h2>年龄:{{Person.age}}</h2>
  <h2>tel:{{Person.tel}}</h2>
  <button @click="changeName">修改姓名</button>
  <button @click="changeAge">修改年龄</button>
  <button @click="changePerson">修改Person</button>
 </div>
</template>
<script lang="ts" setup name="Watch">
import { reactive,computed ,watch, toRef} from 'vue';
  let Person = reactive({
    name: 'zs',
    age: 18,
    tel: '13888888888',
  });

  function changeName() {
    Person.name += '~';
  }
  function changeAge() {
    Person.age += 1;
  }
  function changePerson() {
   Object.assign(Person,{
    name: 'ls',
    age: 20,
    tel: '13888888888',
   })
  }
 
  watch(Person,(newValue,oldValue)=>{
    console.log('Person的值发生了变化',newValue,oldValue);
  },{
    immediate:true,//立即监视
    deep:true,//深度监视
  })
</script>
<style scoped>

</style>

情况四:监视ref 或reactive 定义的对象类型,数据中的某个属性,注意点如下:

  1. 若该属性不是 对象类型 ,需要写成函数形式
  2. 若该属性值依然是 对象类型 ,可直接编,也可以写成函数,不过建议写成函数

总结:监视的要是对象里的属性,那么最好写函数式。注意点:若是对象监视的是地址值,需要关注对象内部,需要开启深度监视。

<template>
  <div>
  <h1>Person</h1>
  <h2>姓名:{{person.name}}</h2>
  <h2>年龄:{{person.age}}</h2>
  <h2>汽车:{{person.car.c1}}--{{person.car.c2}}</h2>
  <button @click="changeName">修改姓名</button>
  <button @click="changeAge">修改年龄</button>
  <button @click="changeCar1">修改汽车1</button> 
  <button @click="changeCar2">修改汽车2</button> 
  <button @click="changeCar">修改整个汽车</button> 


 </div>
</template>



<script lang="ts" setup name="Watch">

  import { reactive,computed ,watch, toRef} from 'vue';
  let person = reactive({
    name: 'zs',
    age: 18,
    car:{
      c1:'奔驰',
      c2:'40W'
    }
    });
    function changeName(){
      person.name += '~';
    }
    function changeAge(){
      person.age += 1;
    }
    function changeCar1(){
      person.car.c1 = '奥迪';
    }
    function changeCar2(){
      person.car.c2 = '大众';
    }
    function changeCar(){
      person.car = {
        c1:'雅迪',
        c2:'艾玛'
      }
    }
    watch(()=>{return person.name},(newValue,oldValue)=>{
      console.log('person的name发生了变化',newValue,oldValue);
    })
    watch(()=>person.age,(newValue,oldValue)=>{
      console.log('person的age发生了变化',newValue,oldValue);
    })
    watch(()=>person.car,(newValue,oldValue)=>{
      console.log('person的car发生了变化',newValue,oldValue);
    })
  
</script>
<style scoped>

</style>

情况五:一个包含上述内容的数组

<template>
  <div>
  <h1>Person</h1>
  <h2>姓名:{{person.name}}</h2>
  <h2>年龄:{{person.age}}</h2>
  <h2>汽车:{{person.car.c1}}--{{person.car.c2}}</h2>
  <button @click="changeName">修改姓名</button>
  <button @click="changeAge">修改年龄</button>
  <button @click="changeCar1">修改汽车1</button> 
  <button @click="changeCar2">修改汽车2</button> 
  <button @click="changeCar">修改整个汽车</button> 


 </div>
</template>


<script lang="ts" setup name="Watch">

  import { reactive,computed ,watch, toRef} from 'vue';
  let person = reactive({
    name: 'zs',
    age: 18,
    car:{
      c1:'奔驰',
      c2:'40W'
    }
    });
    function changeName(){
      person.name += '~';
    }
    function changeAge(){
      person.age += 1;
    }
    function changeCar1(){
      person.car.c1 = '奥迪';
    }
    function changeCar2(){
      person.car.c2 = '大众';
    }
    function changeCar(){
      person.car = {
        c1:'雅迪',
        c2:'艾玛'
      }
    }
    watch([()=>person.name,()=>person.car.c1],(newValue,oldValue)=>{
      console.log('p发生了变化',newValue,oldValue);
    },{deep:true})
  
</script>
<style scoped>

</style>

watchEffect

  • 官网:立即执行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数
  • watch vs watchEffect
    • 都能监听响应式数据的变化,不同的是监听数据变化的方式不同
    • watch:要明确指出监视的数据
    • watchEffect:不用明确指出监视的数据(函数中用到哪些属性,那就监视哪些属性)。
<template>
    <h2>当前水位{{ height }}·C</h2>
    <h2>当前水温{{ temp }}cm</h2>
    <button @click="addHeight">addHeight+10</button>
    <button @click="addTemp">addTemp+10</button>
  
</template>

<script lang="ts" name="WatchEffect" setup>
import { ref,watch,watchEffect }   from 'vue'

let height = ref(0)
let temp = ref(10)

const addHeight = () => {
    height.value+=10;
}
const addTemp = () => {
    temp.value+=10
}

// watch([temp,height],(value)=>{
//     let [newtemp,newheight] = value;
//     if(newtemp>30||newheight>100){
//         console.log('给服务器发请求');
//     }
   
// })

//watchEffect会立即执行一次,然后当依赖项发生变化时,再次执行

watchEffect(()=>{

    if(temp.value>30||height.value>100){
        console.log('给服务器发请求');
    }
})
</script>

<style scoped>
</style>

标签的ref属性

作用:用于注册模版使用

  • 用在普通DOM标签上,获取的是DOM节点
  • 用在组件标签上,获取的是组件实例对象

App.vue 部分代码


<template>
    <h2 ref="title3">你好</h2>
    <button @click="showTitle">show标题</button>
    <RefTest ref="ren"/>
    

</template>

<script lang="ts" setup name="app">
 import { ref } from 'vue'; //引入ref
    let title3 = ref(); //定义ref
    let ren = ref(); //定义ref
    function showTitle() {
        console.log(ren.value); //使用ref
    }

</script>

RefTest.vue

<template>
    <div>
        <h1 >中国</h1>
        <h2 id="title2">北京</h2>
        <h3 ref="title3">故宫</h3>
        <button @click="showLog">点击我输出h1这个元素</button>
    
    </div>
</template>
<script lang="ts" setup name="RefTest">
import { ref,defineExpose} from 'vue'
//创建一个title3,用于存储ref标记的内容
let title3 = ref(null)
let a = ref(0)
let b = ref(1)
let c = ref(2)

function showLog() {
    // console.log(document.getElementById('title2'));
    console.log(title3.value);
}

defineExpose({
    a,
    b,
    c
})
</script>
<style scoped></style>

在这里插入图片描述

回顾TS

Review.vue

<template>
  <div>
    <h1>ts回顾</h1>
    <ul>
      <li v-for="item in personList" :key="item.id">{{item.name}}</li>
    </ul>
  </div>
</template>
<script></script>

<script lang="ts" setup name="ER">

import {type PersonInter,type Persons} from '@/types'

// let person:PersonInter ={id:1,name:'张三',age:60}



// let personList:Array<PersonInter> = [
//   {id:1,name:'张三',age:60},
//   {id:2,name:'李四',age:50},
//   {id:3,name:'王五',age:40},

// ]

let personList:Persons = [
  {id:1,name:'张三',age:60},
  {id:2,name:'李四',age:50},
  {id:3,name:'王五',age:40},

]
</script>

<style scoped>

</style>

index.ts

//定义一个接口,用于限制person对象的具体属性

export interface PersonInter{
    id:string
    name:string
    age:number
}


//一个自定义类型
// type Persons = Array<PersonInter>  //法一
export type Persons = PersonInter[]  //法二

//暴露有三种形式

效果
在这里插入图片描述

props

组件关系: 父传子,子展示
在这里插入图片描述
一、传
Props.vue

<template>
  <h2>  {{ a }}</h2>
</template>
<script lang="ts" setup name="Person">
import {defineProps} from 'vue'
defineProps(['a'])
</script>

App.vue 部分代码


<template>
    <h2 ref="title3">你好</h2>
    <button @click="showTitle">show标题</button>
    <Props a="haha"/>
    <ReviewTs/>

</template>
<script lang="ts">

//JS或TS
import Props from './components/Props.vue';

<script lang="ts" setup name="app">
 import { ref,reactive } from 'vue'; //引入ref

</script>
<style scoped>
/* 样式 */
</style>


效果:
在这里插入图片描述

二、存
Props.vue

<template>
  <h2>  {{ a }}</h2>
</template>
<script lang="ts" setup name="Person">
import {defineProps} from 'vue'

//接收a
// defineProps(['a']) 
// console.log(a)  打印不了a 的值

//接收a ,同时将props保存起来
let x = defineProps(['a'])
console.log(x)
console.log(x.a)  //打印a 的值



</script>

console效果:
在这里插入图片描述

三、

这里是引用
<h2 a="1+1" :b="1+1" ref="123"></h2>
a = “1+1” 字符串 ==》a = “1+1”
:b=“1+1” 是表达式 ==》 b = 2
ref是特例,不用+冒号

Props.vue

<template>
  <h2>  {{ a }}</h2>
  <h2>{{ list }}</h2>
  <ul>
    <li v-for="item in list" :key="item.id">{{ item.name }}=={{ item.age }}</li>
  </ul>
</template>
<script lang="ts" setup name="Person">
import {defineProps,withDefaults} from 'vue'
import {type Persons} from '@/types'

//接收a
// defineProps(['a']) 
// console.log(a)  打印不了a 的值

//接收a ,同时将props保存起来
// let x = defineProps(['a'])
// console.log(x)
// console.log(x.a)  //打印a 的值


//接收a,list
// let y = defineProps(['a','list'])


// 只接受list 会出问题 
// defineProps(['list'])
//循环:<li v-for="p in list" :key="p.id">{{p.name}}</li>


//接收list + 限制类型
//defineProps<{list:Persons}>()


//接收list + 限制类型 + 限制必要性 + 指定默认值
withDefaults(defineProps<{list?:Persons}>(),{
    list:()=>[{
        id:'1',
        name:'张三',
        age:18
    }]
}) //父不传,儿来个默认值



</script>

生命周期(组件的一生)理解

组件的生命周期:

  • 创建 created
  • 挂载 mouted
  • 更新 update
  • 销毁

vue2

创建 (创建前 beforeCreate,创建完毕created)
挂载 (挂载前 beforeMount 、挂载完毕mounted)
更新 (更新前 beforeUpdate,更新完毕updated)
销毁 (销毁前 beforeDestroy,销毁完毕destroyed)
4个阶段 8个钩子

vue3

创建 (setup console.log("创建")
挂载 (引入onBeforeMount,onMounted
挂载前 onBeforeMount()=>{ console.log("挂载前")}
挂载完毕 onMounted()=>{ console.log("挂载完毕")}
更新 (引入onBeforeUpdate,onUpdated
更新前 onBeforeUpdate()=>{ console.log("更新前")}
更新完毕 onUpdated()=>{ console.log("更新完毕")}
卸载(引入onBeforeUnmount,onUnmount
卸载前 onBeforeUnmount()=>{ console.log("卸载前")}
卸载完毕 onUnmount()=>{ console.log("卸载完毕")}

子先挂载完毕,父后挂载完毕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值