VUE3
vite的构建工具的使用
1.在终端中 执行 npm run dev ,才能启动服务,实时的
需要在xxx.vue文件内写三个
<template></template>
<script lang="ts"></script>
<style></style>
需要在main.ts文件写三行
import { createApp } from "vue";
import App from './App.vue';
//作用 是创建营运g
createApp(App).mount('#app');
setup函数,组件初始化执行一次
1.几乎所有的vue代码,都要写在setup函数当中,
2.要求,在最后的时候 返回数据,数据用在模板当中,在template标签中使用
3.模板标签中自动解析 setup函数的结果
在子组件里面写。将来在跟组件里面注册
setup暴露的是对象,暴露出来的 用两个大括号来取
在子组件里面创建页面
1.首先创建一个xx.vue的文件,在文件里面 有 三大标签
<template> 写页面的内容
<div>
<h1>姓名:{{name}}</h1>
<button @click="phone">显示手机号码</button>
</div>
</template>
<script lang="ts"> 写页面的内容
let aname :string ="张三";
let bphone :string = "123222212313"
function showphone (){
alert(bphone);
}
//在这个里面要写setup()函数,并且返回值是对象,还可以是函数,叫渲染函数,如果返回是渲染函数,那就会将template这个nei'r
setup(){
return{
key:值
name:aname,
phone:showphone
//将来这个key可以放在上面的template中标签所需要内容的地方
}
}
</script>
<style>页面的样式</style>
2.需要在根组件里面 做三件事情,
第一:导入xx.vue文件 使用:import Person from './components/Person.vue';
第二:注册:使用:components:{Person}
第三:使用组件,在 根文件的地方写组件<Person></Person>
在ref 和reactive中底层原理
1.ref底层基于setter,调用的是getter方法 ,获取值,然后在setter方法里面,先修改,然后在渲染
牢记;ref 包裹的原始数据,在template中 需要 xxx.value
2.reactive底层基于代理,是js内置的proxy代理对象,然后将目标对象包裹,生成代理对象,然后修改目标对象。
牢记:reactive包裹的是必须 是 对象,包裹原始数据,不起作用,深层响应也会,reactive不需要value
指令v-bind 写在 template模板中
1.v-bind 也可以简写 直接写:就行了
2.如果需要响应式,那就弄响应式,绑定不一定是响应式的内容,如果需要在修改
绑定 字符串 以及布尔值 数组
1.关于布尔值 用在disable联合使用,表示按钮 或超链接 能不能点的问题
-
v-bind 可以使用对象的形式,绑定多个属性,就是在对象里面写多个属性
-
关于动态属性绑定,就是 使用 :【】 中括号,将属性放在中括号里面,就可以实现动态
-
绑定数组的话,可以同过boolean值,来控制属性 是否起作用。
v-model 双向数据绑定
1.修改脚本中的数据 页面上的更新,反过来 ,一样
2.就是 脚本 页面 双向改变
就是template 里面改的话,script里面的数据也会变,反过来也一样。
$event 代表发生的事件,有事件源,event.target
watch监视
监视4中数据:一个函数一个返回值,一个ref ,一个reactive,或者上面三个任意组合的数组。
1.监视使用watch("被监视的对象",回调函数(新,旧)=》{},配置项) ,配置项也就是什么时候监视
2.如果想停止的话,直接调用他的返回值函数,比如 let a = watch(); 在回调函数里面调用a();
3.监视ref包裹的refimpl的value,的proxy代理对象,可以监视,但是porxy里面的值监视不到,默认监视 value这个层级,对象里面的age和name监视不到。
4.如果想深度监视,加一个【deep:true】,在那个配置项的地方,添加
5.新对象和 旧对象,是两个地址,修改属性,不会切换对象,所以不会
6.当reactive包裹对象的话,默认开启深度监视,关不掉。当修改整个人的属性时,使用object。assign(person,{a:''a''})
7.监视对象中的某个属性,如果是属性是普通类型,需要提供getter函数
8.当提供的是一个对象类型,就需要用 对象.对象就行了,就是某个对象里面存一个对象,就这样调用,就只监视这个对象
9.如果里面是对象,也提供getter函数的话,当getter函数的返回值变化了,就能监视,就是修改整个对象,就会监视到。
最终方案:当监视响应式对象中的某个属性时,如果是基本类型,就提供getter函数。如果响应式对象中的某个属性是对象类型,建议也是用getter函数,并且开启深度监视。【deep:true】
<template>
<div>
<h3>语文成绩:{{ chineseScore }}</h3>
</div>
<div>
<h3>数学成绩:{{ mathScore }}</h3>
</div>
<button @click="changeChinese()">修改语文成绩</button>
<button @click="changeMath()">修改数学成绩</button>
</template>
<script lang='ts' setup>
import { ref, watch } from 'vue';
let chineseScore = ref(0);
let mathScore = ref(0);
function changeChinese(){
if(chineseScore.value<100){
chineseScore.value+=10;
}
}
function changeMath(){
if(mathScore.value<100){
mathScore.value+=10;
}
}
watch([chineseScore,mathScore],(val)=>{
if(chineseScore.value>=90 && mathScore.value>=90){
console.log("成绩优秀u")
}else if(chineseScore.value>=80 && mathScore.value>=80){
console.log("成绩良好")
}else if(chineseScore.value>=60 && mathScore.value>=60){
console.log("成绩及格")
}else{
console.log("成绩不及格")
}
},{})
</script>
<style scoped>
</style>
计算属性
computed(()=>{} ),参与的属性只要发生变化,就会执行,
<template>
<div>
性:<input type="text" v-model="firstName">
</div>
<div>
名:<input type="text" v-model="lastName">
</div>
<div>
{{firstName}}-{{lastName}}
</div>
<div>
{{firstName.slice(0,1).toUpperCase() + firstName.slice(1)}}-{{lastName}}
</div>
<div>
{{allName}}
</div>
<button @click="changeName()">修改名字</button>
<button @click="changeName2()">修改名字2</button>
</template>
<script lang='ts' setup>
import { computed, ref } from 'vue';
let firstName = ref("zhang")
let lastName = ref("san")
function changeName(){
firstName.value="li";
lastName.value="si";
}
function changeName2(){
allName.value="jackonso-12"
}
let allName = computed({
get(){
return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + "-" + lastName.value;
},
set(val){
const [a,b] = val.split("-")
firstName.value=a;
lastName.value=b;
}
})
</script>
<style scoped>
</style>
watch监视 和computed的区别
1.机理差不多,
watchEffect模糊监视(直接写回调)
标签上的ref属性(一般在组件上使用)
1,在单网页开发中,现在id 用的不多了,用ref,spa应用就是单网页应用
2.在普通标签上可以用ref 在组件上也可以用ref ,
3.在组件上使用ref上,一般在组件上使用,标记组件,就代表着一个组件。也是ref("myson"),myson。value就是组件的对象。
4.通过defineExpose({数据1:数据1,数据2:数据2,数据3:数据3}) 将数据暴露出去 给父组件,通过父组件的实例 点 访问暴露的东西、
5.在组件上使用,也就是son的数据,通过暴露出来,可以给父组件使用
defineExpose子向父传数据,父可以改子的数据,使用对象来接收数据
<template>
<H3>这个是子组件</H3>
</template>
<script lang='ts' setup>
import { ref } from 'vue';
//这个是普通的属性
let username = "jack";
//这个是响应式的属性
let age = ref(10);
//这个是函数
function mysonbtn(){
console.log("这个是myson的函数...执行了")
}
defineExpose({username,age,mysonbtn});
</script>
----------------------------------------------------------------------------------------------------------------------
<template>
<h3>这个是父组件</h3>
<son ref="myson"></son>
<button @click="show()">获取子组件的数据</button>
</template>
<script lang='ts' setup>
import { ref } from 'vue';
import son from './son.vue';
let myson = ref();
function show(){
//这一行体现出来,子组件的数据,可以通过父组件使用,因为暴露出来了 所以可以使用。
console.log(myson.value.age + myson.value.username + myson.value.mysonbtn())
}
</script>
<style scoped>
</style>
props 父向子组件 传数据,传给子 子不能修改数据。defineProps使用数组来接收数据
<template>
<h3>这个是父组件</h3>
<son name="username" :list="arraylist"></son>
</template>
<script lang='ts' setup>
import son from './son.vue';
let username = "jack";
let arraylist = [
{id: "1",username: "jack"},
{id: "2",username: "lucy"}
];
</script>
----------------------------------------------------------------------------------------
<template>
<div>
<h3>这个是son组件</h3>
<h3>姓名:{{ name }}</h3>
<ul>
<li v-for="son in list" key="son.id">
{{ son.id }},{{ son.username }}
</li>
</ul>
</div>
</template>
<script lang='ts' setup>
//也可以限定 父组件传过来的数据类型,类型可以使用type定义
let obj = defineProps<{name: number,age: number,list?:类型}>()
defineProps(["name","list"])
//可以指定给默认值,list不是给了个问号吗?父可传 可不传 用默认值
用withDefaults(将defineProps包裹后,第二个参数 ,给赋值 )
withDefaults(defineProps<{name: number,age: number,list?:类型}>(),{
list:()=>[{id: 1,name:"张三",age = 20} ]
})
</script>
<style scoped>
</style>
setup执行流程
1.setup组件创建的时候执行,只创建一次,
在setup中 其实是两个域,局部变量就不会冲突。一般不会在使用id了,获取dom元素。
vue3的生命周期,4个阶段7个钩子
1,创建,在setup函数的执行,就是创建阶段
2,挂载,onBerforMount,使用onBerforMount(()=> {} ),在setup()创建的时候就会绑定回调,但是回调不会执行。
3,更新,onUpdated,模板需要更新,
4,卸载,销毁资源
创建 挂载前 挂载完成 更新前 更新完成 销毁前 销毁
组合API和选项式API的区别
1.选项式:所以的东西都分类放的,但是需要完成一个功能 需要多个地方协调,取东西
2.组合式:一个业务需要的数据 全部放在一起
hooks
就是将 方法和参数 放入ts文件里面,然后用一个函数包装,然后返回。
路由(解决单网页中,让用户可以历史操作)
1.一个路由 就是一个组件,有很多key ,一个key对应一个vue,route,key就是请求路径,router管理map集合,
2.比如:一个页面,点a,就显示A组件
-----------------------AB ------------------------------------
<template>
<RouterLink to="/a">A组件</RouterLink>
<RouterLink to="/b">B组件</RouterLink>
<RouterView></RouterView>
</template>
<script lang='ts' setup>
import { RouterLink } from 'vue-router';
</script>
<style scoped>
</style>
-------------------------A --------------------------------------
<template>
<h3>A.....</h3>
</template>
<script lang='ts' setup>
</script>
<style scoped>
</style>
-----------------------------B------------------------------------
<template>
<h3>B.....</h3>
</template>
<script lang='ts' setup>
</script>
<style scoped>
</style>
-----------------------main.ts-----------------------
import { createApp } from "vue";
import App from './App.vue';
import router from "./components/router";
//作用 是创建营运g
let app = createApp(App);
app.use(router);
app.mount('#app');
//createApp(App).mount('#app');
----------------------router中的index.ts--------------------------
import { createRouter, createWebHistory } from "vue-router";
import A from "../A.vue";
import B from "../B.vue";
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/a",
component: A
},
{
path: "/b",
component: B
}
]
})
export default router;
路由器工作模式(hash 和history模式)
const router = createRouter({
//在这个地方修改 hash就行了
history: createWebHistory(),
routes: [
{
//可以给router起名字,就叫a
name:"a"
path: "/a",
component: A
},
{
path: "/b",
component: B
}
]
})
to的三种方式
<RouterLink to="/a">A组件</RouterLink>
<RouterLink :to="{path: '/a'}">A组件</RouterLink>
<RouterLink :to="{name: 'a'}">A组件</RouterLink>
子路由的路径 不能/开头
emit自定义事件,比如鼠标单击等等
const emit= defineEmits(['get-love']);
插槽
1.当父 向 子 动态注入自定义内容或者结构
2.子 作为 容器 父组件 控制内容 这个时候用插槽
3.在父类中,使用category,在标签内写内容,可以多个容器,在子组件里面 可以写一个solt标签,内容就会搞过来
具名插槽
在<category v-solt:名字> 配合着 v-solt:名字使用,,可以简写:#名字。
,2.
作用域插槽
自定义ref ,就是要写回调,将来有人调用
1 ,customRef
teleport传送
属性to;就是传送到哪?