vue3-day1

1.vue3创建:在cmd中

2.vue3的compositionAPI

  和v2的options对比:

    v2是把几个对象的数据放data里,把几个对象的方法放在methods里面,对于每个对象来说太分散了。v3就是会把一个对象的所有东西放在一起的

3.setup(){   return()}

做法:把export defalut{

           setup(){

                            //对于数据,即原来的v2的data(){}

                            let name = '张三',//此时的数据不是响应式的,页面不会变,但是数据内容改变

                            let age = 18,

                            //对于方法,即原来的v2的methods

                          function changeage(){

                                name = '李四'

                            }

                            return{name,age,changeage}  //把写的东西交出去。

                          }

}

①因为setup()执行是在beforecreate之前,还未进行数据代理。

②setup()中的this是undefined(v3弱化了this),setup里面不可以用this

③setup的返回也可以是个函数,return ()=>{....//函数}   会把上面所有内容覆盖掉了。

④:(很重要的) 

   v2中的data和methods可以和setup共存。

    原来v2写法,可以用this.数据名去访问setup中的数据的,但是setup中不可以去访问外面v2写法data中的数据。

4.setup语法糖:(setup的简写)

原来setup写法:

<script  lang='ts'>


export default {
    name: 'person',
            setup(){
                //定义数据
            let name='张三'
            let age= 18
            let tel='123123'  //不要加逗号

            //定义方法
            function showTel(){
                alert('tel')
            }
            function changename(){
                name = '李四'  //这里数据是未响应的!!


            }
            return {name, age, tel, showTel, changename}  //这里用花括号
        },
        
    
   

}
</script>

   现在简写为:

    不用写setup()和return了!!!

     但是多写一个<script lang='ts' setup>   //把所有的setup的内容写这里 </script>

<script  lang='ts'>


export default {
    name: 'person',
 
}
</script>



<script lang='ts' setup>

                //定义数据
            let name='张三'
            let age= 18
            let tel='123123'  //不要加逗号

            //定义方法
            function showTel(){
                alert('tel')
            }
            function changename(){
                name = '李四'  //这里数据是未响应的!!


            }
          
      
        
</script>

        对于第一个script是为了配组件名字的,第二个配置内容的!!

5.响应式数据:谁改变谁是响应式的数据

  ref(参数):基本类型及对象型:

  首先在<script> </script>中引入:import {ref} from 'vue'

  其次是对于数据想变成响应式的:  let name = ref('张三'),

   对于方法的话,想让里面的值(属性名.value才能修改数据)改变则:function changename(){ name.value='李四'}

rective对象类型响应式数据:

先引入reactive,再给数据添加reactive()

<script lang='ts' setup>
import {reactive} from 'vue'  //这里是花括号的
let car = reactive({name:'奔驰', price:10000})

//函数修改
function changeprice(){
car.price += 10 } //直接用对象.属性名




 </script>

         注意:表面上是ref处理对象型的数据,但是其实ref还是调用了reactive去处理对象型数据的。

   注意:1.如果修改掉原来的reactive对象,则无法修改。如:原来是: 车=奥迪,价钱。现在改为雅迪,车价。里面全改了就不行了。要用object.assgin(要改的对象名,要改成什么的内容)  。

  如果基本类型和简单的对象都用ref,深层次的对象用reactive。

    如果做表单收集也最好用reactive。(看实际吧)

6.torefs:

目的:从reactive对象中拿到的数据并不是响应式的,为了使得拿到的值也是响应式的就用torefs()

import {reactive, toRefs} from 'vue' //引入这两个

let person = reactive({
         name:'张三'
         age:18
}) //这是个对象型的{.....}

let {name, age} = toRefs(person) //把reactive对象改成ref

.......

,let name = person.name 虽然person是reactive的,但是person.name只是取到这个值,而name又变成不响应了,所以 let{name} = toRefs(person)

  7.v3的computed属性:

           首先用import引入computed,可以把fullname写成方法或者计算得到,前者无缓存,后者是若两次数据同就直接从缓存拿出。

        

<template>
  <div class="person">
     姓:<input type="text" v-model="firstname"> <br>

      名:<input type="text" v-model='lastname'> <br>

      全名:<span>  {{ fullname }}   </span>

  </div>
  </template>
  <script lang="ts">
      export default {
        name: 'person'
      }
    
</script>

<script lang='ts' setup >
    import {ref, computed} from 'vue'

    let firstname = ref('zhang')

    let lastname = ref('三')

    //计算得到fullname,并且让首字母大写(slice选取第一个字符并且大写,slice选取除了第一个字符进行拼接)
    let fullname = computed(( )=>{
        return firstname.value.slice(0,1).toUpperCase() + firstname.value.slice(1) + '-' + lastname.value
    })

</script>

   缺点是:上面的计算方法中对于值来说只能读,不可修改。

  因此计算属性函数用set()去修改,用get()去得到数据。而不是去用函数定义了。

 let fullname = computed({
     get() {

        return   firstname.value.slice(0, 1).toUpperCase() + firstname.value.slice(1) + '-' + lastname.value
     },
     set(val){ 
              const [str1,str2]=  val.split('-')  //注意的是:把val以-为分隔符,
              firstname.value = str1
              lastname.value=str2

     }
    })

8.watch监视

     写法: import {watch} from vue

     函数:watch(监视谁, 回调函数)

   用处例子:监视若数据大于10000可以请求一个优惠券。

   只会监视四种数据:

  ① ref型的基本类型:

监视和停止监视(if判断如果newvalue大于10就调用stopwatch函数,停止监视)

②  ref类型的对象类型数据:

  在watch()中第三个参数添加deep:true.开启深度监听。

对于stu {年龄,对象},若只是年龄或者对象改变,并不能监听到旧值的。类似于旧房子只是桌子椅子改变了。只有整个房子改变时才能监听到新旧值。(内存地址不一样了)

  

③ resctive数据

   reactive缺点不可以整体修改整个对象的,只能用boject.assgin()来修改

   reactive定义的数据默认是开启深度监听的,而且是无法关闭的!!

   但是新旧值是不变的。

④getter函数的返回值

   4.1监视响应式对象中的某一个属性,该属性是基本类型的,要写成函数式。

  

     person是响应式的,但是person. name不是响应式的。要在watch中把监视谁中person.name改写成一个回调函数的return 值。 watch(() => {person.name} ,  ......)

       4.2监视响应式对象某一个属性,该属性是对象类型,可以直接监视或者写成函数式。若还想监视这个对象里面的细节变化就加个deep:true.

   

⑤包含以上三种内容的数组

    watch([()=>person.name,()=>person.car], 回调函数(参数){..})  用一个数组把所有要监视的包含进去。

9.watchEffect:达到某个值会请求。

  首先引入watcheffect。

   应用时不用交代监视谁,watcheffect(()=>{......//要判断的条件和结果}),不用再写监听谁了。

   10.标签的ref属性:

   <h2 ref = 'time'>...</h2>

   创建一个time,用于存储ref标记的内容

     let time = ref()  //time是自己取名的,上下一致就行。

作用:加了ref只会在本页面执行关于time的,防止和其他页面id=time会混。

 补充css: 在<style scoped> 这个也是只会在本页面添加属性,不影响其他页面,无脑加上!

   总结:ref放在html标签获得dom对象,ref放在组件中获得是实例对象。

v3中若把ref放在组件里,需要用defineExpose()去拿实例对象中某个数据。

11.TS接口:(问题在于报错.ts不在app.json中)

  1.

<script lang='ts' setup >
    import {type PersonInter} from "@/types"

    let person:PersonInter = {id:'123',name:'张三', age:15}


</script>

  

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

ts泛型:......

let  person:Array<personInter(接口),....,>

12.props使用:

 

  左边是app.vue管理所有组件的,右边是app管理的一个组件person.vue.

 要用组件person:先import引入,再调用person标签。

  现在app(父)给perso(子)传递数据时:

       ①从person的标签中传入数据 

               :list='personlist'

            //personlist是父中的数据,list是个参数而已,别忘带冒号(冒号是读父中数据personlist,             把数据用参数list传过去)

    ②子接收数据:

        引入defineprops:  import {defineProps} from 'vue'

      调用defineprops去接收传来的数据: defineProps(['list(list是参数名)'])

            接收list后子页面就有相关的数据了,就可以用在需要地方: z这里用在了<li>进行v-for遍历。

  ③:子接收数据list时还要对数据限制接收:

          子接收:defineprops <{list:persons}>()  //persons是限制的类型

④:接收数据,限制类型,指定默认值(withDefaults):

          withDefaults(definedProps<{list? :persons}>(),   {list:()=>[...])

            //list是传来的参数,persons是限制条件,后面函数是若夫没给,就用这个默认值。

  13.生命周期(组件的一生):

       创建,挂载,更新,卸载。

  创建直接用setup,没有前后了。

  v3的挂载:挂载前是 onBeforeMount( ()=> {//函数体}) 挂在前会执行箭头函数内容。

                     挂载是onMounted( ()=> {.....})

     更新是onBeforeMount,OnUpdated...

 (子先挂载完,夫再挂载完)

14自定义hooks:

    ①hooks单独创建一个文件夹。文件夹下面是.ts或者.js文件

    ②把原来在person组件中<script> </script>中的内容:

          h2标签的求和方法,传一个初始值数据。 img标签的请求狗图。

</script>


<script lang='ts' setup >
import { ref, reactive } from 'vue'
import axios from 'axios'


let sum = ref(0) //数值数据


//想把狗图插入到按钮下面,先把图片用数组存一下,在img标签中遍历v-for

let dogList = reactive(['https://images.dog.ceo/breeds/pembroke/n02113023_4038.jpg'])  //图片数据


//方法
function add() {
    sum.value += 1
}

//再来一只,请求网址,把返回的图放在img中,失败就弹窗提示
async function getDog() {
    try {

        let result = await axios.get('https://dog.ceo/api/breed/pembroke/images/random') //axios请求一个图,用result接收
        dogList.push(result.data.message)  //把返回的message放到数组doglist中

    } catch (error) {
        alert(error)

    }
}





</script>

     ③现在用hooks文件改成  useDog.ts 这个ts中包含请求狗图操作!

                                         useSum.ts 这个ts中包含传值的数据和方法求和内容!

      把相关数据和方法都封装成一个函数,并且暴漏出去。还要return返回所写的方法和数据内容

import { ref, reactive } from 'vue'
import axios from 'axios'
//把狗图插入到按钮下面,先把图片用数组存一下,在img标签中遍历v-for
export default function(){
let dogList = reactive(['https://images.dog.ceo/breeds/pembroke/n02113023_4038.jpg'])  //图片数据


//再来一只,请求网址,把返回的图放在img中,失败就弹窗提示
async function getDog() {
    try {

        let result = await axios.get('https://dog.ceo/api/breed/pembroke/images/random') //axios请求一个图,用result接收
        dogList.push(result.data.message)  //把返回的message放到数组doglist中

    } catch (error) {
        alert(error)

    }
}

return {dogList, getDog}


}

import { ref, reactive } from 'vue'

export default function(){
let sum = ref(0) //数值数据

//方法
function add() {
    sum.value += 1
}

//除了要封装成函数而且暴漏接口,还要把数据和方法都return出去
return {sum, add}


}
<script lang='ts' setup >
import useDog from '@/hooks/useSum'
import useSum from '@/hooks/useSum'

const { sum, add } = useSum()
const { dosList, getDog } = useDog()






</script>

  在原来的文件中引入,再调用函数,返回值用一个let{.....}来接收。

   15.路由 route, 路由器 router

路由=key +value

多个路由组成路由器

①创建导航区和展示区在app.vue 根组件中

<template>
  <div class="app">
    <!--标题-->
    <h2>路由测试</h2>

    <!--导航栏-->
    <div class="navigate">
        <a href="#">首页</a><br/>
        <a href="#">新闻</a><br/>
        <a href="#">关于</a><br/>

    </div>

    <!--展示区-->
    <div class="content">
        s
    </div>

  </div>
    
</template>

<script lang="ts" setup>

  
</script>

<style>
</style>

②请来路由器:

首先在src下面建立router文件夹,里面放index.ts  

(为了配路由规则。把路由引入到各个页面)

其次创建compoents文件夹里面放三个组件。

每个组件对应展示区跳转的页面。

最后在main.ts中配置路由器

//router文件夹是用来引入路由器

import {createRouter, createWebHistory} from 'vue-router' //引入路由器,后者是规定v3路由是用什么模式

//要引入组件。 因为电点击不同按钮会跳转不同页面,这些页面是用组件写的。
import Home from '@/components/Home.vue'
import About from '@/components/About.vue'
import News from '@/components/News.vue'


//创建路由器:用ceraterouter()函数
const router = createRouter({
    history:createWebHistory(),//指定路由器是hash(后面有)
    routes:[{   //写路由规则的。
        path: '/home',
        component: Home

    },
        {   //写路由规则的。
            path: '/about',  //path是指http网址后面/path 是/About时,会链接组件About。
            component: About

        },
        {   //写路由规则的。
            path: '/news',
            component: News

        },
]

})

export default router //把路由暴漏出去

  app也是必须要引入的。

//引入createapp用于创建应用
import { createApp } from 'vue'
//引入app根组件
import App from './App.vue'
//引入路由器
import router from './router'

//创建一个应用
 const app=createApp(App)
 //使用路由器
 app.use(router)

 //挂载整个应用到app容器中
    app.mount('#app')  

上面几步都是说配置好路由,/path后会跳转页面。只是制定了规则但是还没能让路由器把页面放到展示区呢。

   ③:在根组件中的展示区引入routerview标签,并且在script中import引入。

  此时修改网址:http://localhost:5173/home就可以跳转

④最后实现点击链接自动跳转

   引入routerlink,并且在导航区中的原来html中<a href>标签全部换成<routerlink to='/path'>..</routerlink>

   补充路由标签中的css: active-class='类名'  //表示这个路由激活时会配上这个类的css,每个标签都可以添加这个类,选谁谁应用css。

16.路由器工作模式:

  history:优点http中无#,美观。但是服务器刷新会有问题

hash模式:兼容性好。有#,且seo优化差

17.命名路由:

     

routes:[{   //写路由规则的。

          name:'shouye'  //这个路由名

        path: '/home',

        component: Home

    },

可以根据路由名或者path去跳转到页面<routerlink :to{//name:'shouye' 或者//path:“/path}>

  18嵌套路由

案例:在路由测试页面中导航栏有三个按钮,可以对应跳转三个展示区(新闻页。首页,关于页面),这个已经用路由实现。

     现在在新闻页面中导航栏有几个标题,每个标题对应跳转不同的页面新闻内容,又要在新闻页面中整一个路由。

 在路由配置新闻页面的配置后面加上children{path不用带/,和compent组件 },并且在新闻业的展示区引入routerview标签。

19.路由-query参数

  在新闻页面有 导航区(各种标题)和展示区(要跳转内容)

   在新闻业面中引入路由,导航栏的每个li标签中添加routerlink标签,这个标签就是点击这个标题就能跳转到路由绑定的页面。

   跳转的页面是一个组件,要有个组件.vue,绑定新闻页面和这个组件通过在路由文件router中路由配置,给新闻业面配置的子孩子是这个组件(配了路径和compoent)。

现在是新闻页面的script中有了数据,想把这些数据传到跳转之后的页面里面去。

通过新闻页面中路由标签中query传入参数给子页面,子页面那边用useroute来接受数据。

  子页面中 import {useRoute} from 'vue-router'

                   let route = useRoute  //接收到数据在route中,而route是一个对象吗,在route中的.query中是传过来的参数。

 想用数据就直接插值语法{{route.query.数据名}}

20.路由中的-params参数

  传参数过程:  

  在router配置文件中的新闻页面的children里面的path:/路径名/:a /:b

 用a,b来占位,表示这里穿的是参数。 而且不能用path跳转了,只能用name跳转

 其次,在新闻页面的导航栏的路由标签中<routerlink to="/详情页的路径/a/b">  //a,b是要穿的数据。

详情页接收:

   引入route,route()返回的数据中有params,直接插值用。

(既然占位了。就要传参数,如果没有要传的参数,就在占位参数后面加上❓

此图还差个新闻业面路由标签中传参数 。

21路由的props配置

  props的底层逻辑,虽说传的是参数,但是底层传的是键值对。

第一种:props:true

   只能baparams参数传给跳转页。

defineprop()是接收父组件传来的参数的。

第二种:自己决定把什么传给路由组件(跳转页)

   props(参数){

  return 参数.query

}

22.路由-replace属性

  push:路由每次跳转的页面都会存在栈中,由页面箭头来返回或前进浏览历史记录(默认是                        push)

replace:  浏览页面会覆盖上一次浏览页面。  在路由标签中添加replace就可以修改模式。

23.编程式导航♥

  就是脱离标签routerlink。

   应用场景: 跳转页面时要一些条件或者要干些其他事,而不是直接点击链接就跳转。

  写法:

   在主页引入userouter(注意是路由器!)。

   调用userouter()

此图目的是点击之后三秒在跳转到新闻页面上。

  在挂载(生成dom放在页面上之前做这个事情)三秒后计时器调用,执行router.push(..),就是push到新闻业。把新闻业放在栈中。  (router类似于董事长,让董事长把新闻业推到栈中去)

   router.push()是一个函数,就是用来跳转页面的,和routerlink中 :to....是实现相同功能的,只是push()可以添加一些事件,所有可以给路由标签绑定一个点击事件,事件执行函数就是router.push.

  

interface是对news传的参数进行限制的。否则会报错any,或者写成news:any也行就是对其不限制了但不推荐。

24pinia

多个组件共享数据采用pinia。

  

  

1.pinia读取数据  

   

pinia是用来存取数据之类的,pinia的具体体现在根目录下的store文件夹,store中文件时.ts,这里面文件和component组件中文件时对应着管理的。

  如:store中的count.ts 存取数据是对应compoents中的count.vue的。

首先引入definestore,state()类似一个仓库,要存的数据直接写在state中。并且把接口暴漏。

2.使用store中数据:

先引入接口useCountStore,再调用。

  

解释:若是响应式对象里面数据是ref类型的,取数据的值时直接拿数据名,不用再.value了

   拿state的数据有两种方式:

   返回的countStore对象中有sum,也有$state里面有个sum,两种都可以得到值。

(这个sum就是store文件中用state(‘存储名字’),{satate....} 中的sum存储名。  就是state中存的数据给它取个名,这个名就是前面state的第一个参数。)

3.pinia修改数据:

第一种:直接修改数据

   stroe中sum数据用countstore.sum可以取出来,如果要修改sum。直接再按钮上绑定点击事件让countstore.sum +=1就行。

第二种:若要批量修改数据用方法.$patch()

  countstore.$patch({

     存储名:值,

    存储名2:值

})

第三中修改方式: actions()

好处是可以对修改变量进行限制条件之类的,复用性好。

  在store文件大的state并排添加actions:{}对象,对象里面写要执行的动作increament函数,再用的时候调用该函数。

    注意:actions要是想要拿到state中的数据要用this.值名 才能取到

4.storetoRef:

作用:从store文件中取出的数据都不是响应式的了,如果给取出的countstore加上torefs,那么countstore对象包含的所有方法和数据都变成响应式的了,代价大,而storeRef只会让countstore中的数据变成响应式的。

5.getters属性

作用:当store中state中的数据需要处理之后再使用时,就在state并排加上getters属性,类似于计算属性。

  

注意::string是因为返回报错为 ....any,解决方法就是upperschool() :string规定一下返回类型是string类型的。

6.$subscribe作用:

 类似于watch监听。 

store中state的数据发生了改变时,暴漏的接口名.$subscribe(()=>{..})就会被调用的。

  25.组件通信:♥♥

1.props实现子父互传(大盒子嵌套一个小盒子)

  ①父传子:

  首先在父中引入子组件import,在父中要用到子组件标签才能显示子组件<子组件/>,

父给子传数据时在子组件标签中写入穿的信息<Child    :car="car" />  (父亲有个数据叫 let car=...)。

子接收父的信息:利用defineProps(要接受哪个参数//从父的子标签中要传的参数找)

 接收后直接用插值语法用这个参数就行。

②子传父:

首先父给子一个函数,子收到这个函数后如果需要给父传参数就调用这个函数。

父亲定义的是gettoy(),通过子组件标签把这个函数传过去并且用变量sendtoy作为传的参数并且接收,子需要时调用sendtoy()并且传入数据,可以执行这个函数。父这边就可以直接调用变量访问值。

2.自定义事件:

补充dom知识:

当要传三个参数,但是只想传两个参数时,就用$event占位符,结果会输出c是一个事件。

  

自定义事件:专门用于子传给父!!!

                写法:①在父页面的孩子标签中 写  @自定义事件名:“回调函数名”  //当自定义事件触                                  发时,就会执行回调函数。

                           ②在子页面中声明这个自定义事件:const emit = defineEmits(['自定义事件                                          名'])

                           ③在任何地方只要写 emit(‘自定义事件名’) 就可以在此处触发该事件。

                           

3.emitt实现任意的组件通信:

                    补充: $bus, pubsub, mitt都是提前绑定事件。

提供数据的:(发布消息)在合适时候触发事件  

接收数据的:(提前订阅消息)提前绑定好事件。(给谁绑定的事件,就找谁触发事件。)

用法:首先emitter文件引入并且暴漏接口

  在main.ts中引入emitter文件:import enitter from 文件名

  例子:

       用emitter绑定和解绑事件:

    

孩子2传给孩子1如图。

注意,组件在卸载时要解绑事件。(写在绑定事件的那个页面上)

 onunmounted ( ()=> {emitter.off('要解绑的事件')})

4.v-model通信:子传父,父传子都可以。

补充:defineProps的大部分用法是进行父子组件传值。defineemitt:子组件触发父组件的的事件,并且进行传值。

v-model在html标签和组件标签传的方式不一样的。

在vue3中@update:modelvalue,@是个绑定事件,@后面就是绑定事件名,没有其他含义。

在普通标签中第五行等价于第六行。

注意:v-model=‘username’,在等价时如果不想写modelvalue这种太长名,在第一种写法中,改为v-model : 别名 =‘username’,这样以后写等价时候可以用别名了。而且这种可以在组件中写多个v-model:别名。

5.$attrs:用于祖孙互传的。

补充:父传子时,如果传多个参数,但是子只收一个参数,剩下参数都在$attrs里面存储着,直接用$attrs插值就可以看到了,不用去接收。

在爷页面中写一些数据,并且在爷页面中的父组件标签中传给父,在父中写入孙标签,在孙标签中写入v-blind = "$attrs'' ,在孙页面中正常接收数据内容。 

 6.$refs:父传子。 $parent:子传父。

如果说父只想获得一个孩子的内容,就用ref=‘名字’,用来标识孩子。

但是父要得到所有孩子内容,就用$refs,这个会把孩子暴漏的所有内容用数组存起来。

孩子用    defineExpose({computer,book})把想让父亲访问的内容暴漏出去。

7.provide 和inject : 用于祖孙传递(没有经过他人传递)

首先在爷页面提供给后代能访问的,后代用inject接收数据。

在孙中接收数据时,是需要设置一下默认值的。

8.用pinia传递。


9.插槽:

        ① 默认插槽:

                案例:一个父组件里面含有三个子组件,而三个子组件内容各不相同。

   做法:在父组件中子组件标签用一对标记,在子组件标签内写入内容。 在子页面中用slotE标签来占位,表示父页面的子组件的内容要放在子组件的位置。

如果说父页面中没有传东西过来时就会用默认内容代替。

  父页面中引用了三次子组件标签就会在页面上呈现三次。

<slot>默认内容<slot/> 如果说父没给子传内容,就会把默认内容显示在页面上。

     ② 具体插槽:

  应用于:每个子组件中含有多个内容,每个内容在每个子组件的插槽位置是不一样的。

把父页面中子组件的内容用<template>标签包含起来,并且指明v-slot=‘名字’。 在子组件中在<slot>标签中用name=‘名字’去找其插槽位置。

【语法糖:  #s2  就是v-slot=‘s2’】

③:作用域插槽

  应用于:数据在孩子那里,但是父亲要访问孩子,才能在父页面中使用这些数据。

         【子组件维护自己的数据,但是结构是由父组件决定的!!!】

子组件中含有数据games,用标签slot中:youxi=‘games’  把游戏内容传给插槽使用者(父),父用v-slot=‘参数名’ 去接收传来的所有的数据(用数组保存所有内容)。 父就可以访问孩子传来的所有的内容了。

26.其他api:

  1.shallowref:提高效率。只关注第一层。

  只会处理浅层的ref。  例如person.value.name=’ci‘,就无法使用了,person.value就已经是第一层的响应了。

2.readonly:

s2=readonly(s1)可以只是读出s1,在s2上去做修改,但是s1还是不会被修改掉的。

shallowreadonly(): 只有第一层会被保护,只能读。  如果是深层的会被修改的。

3.toraw和markraw:

  toraw用于获取一个响应式对象,返回值不再是响应式的了。一般用于将响应式对象传给别人时,又不想让对方直接修改数据内容。

  markraw:标记一个对象,这个对象永远不会是响应式的对象。

4.customref:♥(自定义ref)

  作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行控制。

  优点在于: 对于响应式的数据,一修改页面就会立马修改,现在想要的是修改一秒之后页面再修改,就只能用自定义的ref了。

  首先这个自定义ref一般写在hooks里面的,被封装一下之后暴漏出去的。

initvalvalue是初始值,delay是定时器的值(是传进来的)

customref()里面track是用来让vue跟踪数据的,trigger是让vue直到数据改变了。

  5.teleport:

  应用场景: 父盒子里面有个小盒子,小盒子的定位是以整个窗口为标准的,如果父盒子的图片增加 filter: saturate(0%) 会让图片变成灰色的,此时小盒子的定位就会以父元素为参考对象而不是整个窗口了。

此时就要用传送门teleport。  (就是把标签teleport中间的内容插入到某个地方去。)

6.suspense:?

  应用场景:等待异步事件时渲染一些内容,增加客户体验。

  使用步骤:引入异步组件,使用suspense包裹组件,配置default和fallback。???

 7.v3非兼容性改变 (面试题)♥♥

  • 23
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值