21.vue的学习
1.vue的编程风格,选项式API(vue2)和组合式API(vue3)。
2.vue项目创建:进入到准备好的文件夹,管理员打开命令行执行:npm init vue@latest,项目名称不要大写。
3.Vue的项目结构:结构图如下,执行npm install就是在下载依赖到node_modules,
4.文本插值:
双大括号的文本语法,支持单行的语法,不支持if这种换行的,最好不要在模版也就是双括号里面做操作,最好只接受返回,data里面定义key,和值,HTML中直接双大括号引用,即可拿到,也支持js的语法运算。
纯HTML,双括号返回的是纯文本,如果需要返回标签则不行,需要采用Html的方式 :v-html
5.属性绑定:
也是 v-bind 写法:<div :id="test"> ,原来的是<div v-bind:id="test"> ,由于太常用就直接省略用:来表示,当要绑定的为对象时,还是得用v-bind,
写法如下:<p v-bind="objectTest"></p>
6.条件渲染:
也就是v-if和v-else,如果v-if后面的内容为true,则渲染,为false则渲染v-else的内容,还有v-else-if这个就是给定选择条件,进行渲染。个人觉得后面v-if-else用的多一点。写法如下:
然后是v-show,作用类似于v-if,用法也是接近,但是v-show是基于css的display属性,来进行切换,v-show一开始就会渲染,只是display为:none,有更高的初始渲染开销,v-if一开始不会渲染,有更加大的切换开销,如果需要频繁切换则使用v-show,如果运行时绑定条件很少改变,则用v-if。
7.列表渲染:
也就是v-for指令,循环数组,拿出值,写法为 <div v-for="item of data" :key="item.id"> ,data为要被循环的数组,item为每次循环的结果,:key是为了拿到唯一id作为索引,循环都得加上索引,这样提高效率,后面数据位置改变,渲染的效率更高。
8.事件处理:
v-on指令,简写为@,比如点击事件@click,事件的处理函数写在methods里面,大概例子如下:
事件传参,设置事件函数时,将拿到的参数传给函数,让函数做对应的处理,例子如下
9.数组变化侦测
就是定义一个数组,然后通过事件,对ui和数组进行操作,可以直接显示ui,也可以只加到数组,不显示UI,即在method里面的方法拿到data进行操作如push等操作,UI也会跟着更新。
10.计算属性和函数的区别
计算属性基于响应式依赖被缓存,一个计算属性只会在其响应式依赖更新时才重新计算,方法调用总是在重渲染发生时再次执行函数,也就是说computed里面的函数,只要不变化,多次使用,只会计算一次,但是是methods里面的方法的话,就算函数没变,几次调用就计算几次。
11.表单的输入绑定,v-model指令
即给输入框的值绑定数据,v-model也还有.lazy .number和.trim的属性, .lazy让数据不会实时刷新,.number就是只接受数字类型,.trim去掉前后空格。
12.模块引用:操作DOM
ref属性,给标签设置ref属性在methods中使用 this.$refs.标签的ref值,就可以使用原生的js操作标签,举个例子:this.$refs.container.innerHTML = "哈哈哈",其中containner是一个div的ref属性值,这样就可以做到操作DOM,改变div的值。但是不建议使用,操作DOM消耗比较大。
13.组件注册与组件嵌套
组件注册就是在另外一个组件里,注册其他的组件,让他作为子集在父级显示,这样可以把一个页面拆分为几个组件,这就是组件式开发,也就是组件嵌套。组件注册分为全局注册和局部注册,
全局注册虽然方便,但是不好维护,容易分不清子父集关系,所以一般是用局部注册,即在script中import,在template中以标签显示,在component中初始化。详情如下:
<template>
<Header></Header>
</template>
<script>
import Header from "./pages/Header.vue"
export default{
components:{
Header
}
}
</script>
14.组件传递数据props
props可以将父级的数据传给子集,不能反着来,只能父到子,组合式api可以用provide和inject实现,如下是限制props的传参格式,正常要用props将父级元素传给子集,只需要在注册的template中用v-bind,也就是:,接受父级的数据,在子集中用defineProps来接收,最后拿到渲染。
15.组合式api的ref:
组合式api的ref将数据设置为响应式数据,在setup里面想要用被ref调用的数据,得加.value,渲染数据不用加。既可以定义基本类型,又可以定义对象。reactive只能定义对象,ref是都可以定义。层级深,表单可以用reactive,平时都还是ref,ref和reacttive的区别如下:
toRefs可以将对象转换为响应式对象,比如解构一个对象,,比如一个接口返回的数据很多,然后就需要解构我们需要的数据,直接解构的数据不是响应式,但是加上toRefs就成为响应式,就可以渲染。如下:
16.watch的使用
watch是监视数据,比如当我的age>18岁时,我要联系后端处理,或者订单价格超过1万,的时候我要做什么,很常用。情况如下:
对象监视的深度监视:
watch(car,(newValue,oldVlaue)=>{
console.log(newValue,oldVlaue);
},{deep:true})//这里的car是一个ref对象,开启深度监视,才能监视到对象的属性
但是对于reactive对象,他是默认开启了深度检测的。当需要监视某个对象的单独一个属性时,需要写成函数式,写法如下:
watch(()=>car.price,(newValue,oldVlaue)=>{
console.log(newValue,oldVlaue);
},{deep:true})
当对象的某个属性也是对象的时候,也直接写成函数式。当需要监视多个属性时,采用数组的方式来进行监视。
常用的就是函数写法,然后加上深度检测。
17.hooks:
hooks就是将函数需要的data以及函数进行封装,一直在script里面写会很混乱。注意hooks的命名很重要,一定是如useDog之类的,然后这个TS就包含了所有的关于dog的数据,以及函数,
最后用一个默认匿名函数进行封装和返回,export default function(){},例子如下:
import { reactive } from "vue"; import {type personInner,type persons} from '@/types/index' export default function(){ let person : personInner = {id:'1',name: "lst",age:22} let personList = reactiv<persons>([ {id:'1',name: "lst",age:22}, {id:'2',name: "gy",age:22} ]) return {person,personList} }
18.路由:
引入路由,创建好路由包,以及路由文件后,最后一定将router导出,在文件中写
import { createRouter,createWebHistory} from "vue-router"; import Home from '@/components/Home.vue' import About from '@/components/About.vue' import News from '@/components/News.vue' const router =createRouter({ history:createWebHistory(), routes:[ { path:'/Home', component:Home }, { path:'/News', component:News }, { path:'/About', component:About } ] }) export default router
需要注意的是history:createWebHistory(),是路由的工作模式,还有种hash模式但是hash模式会让url带#,我们一般都采用history的模式,但是需要后端后面去处理404等问题。然后是更改main.js
更改main.js如下
import { createApp } from 'vue' import App from './App.vue' //引入路由器 import router from './router' //创建应用 const app = createApp(App) //使用路由器 app.use(router) app.mount('#app')
再去App.vue里面引用
<template> <div> <!-- 导航 --> <div class="daohang"> <RouterLink to="/Home" >首页</RouterLink> <RouterLink to="/News" >新闻</RouterLink> <RouterLink to="/About">关于</RouterLink> </div> <!-- 展示 --> <div class="main-content"> <RouterView></RouterView> </div> </div> </template> <script lang="ts" setup> import { RouterView,RouterLink } from 'vue-router'; </script>
路由的配置项
name:路由规则的名字。可以用于编程式导航和组件内部的路由跳转。
path:路由的路径,可以包含动态参数和正则表达式。例如,/user/:id 表示用户页面,:id 是一个动态参数。
redirect:路由的重定向规则。例如,{ path: '/', redirect: '/home' } 表示路由根路径的重定向。
component:路由对应的组件。可以是一个普通的组件类或异步加载的组件。
children:当前路由的子路由。可以是一个路由规则数组,也可以是一个函数,动态生成路由规则。
meta:路由的元信息,用于描述路由的一些额外信息。例如,路由是否需要登录、权限鉴定等。
components:路由对应的多个命名视图组件。
路由跳转:
router link组件:可以通过router-link
组件的to方法,上面已经有使用。
router.push
函数:使用router.push
函数以编程方式实现路由跳转,我们只需要在普通按钮上绑定click事件,并在事件中调用router.push()
方法即可实现跳转,示例代码如下:
<template> <div> <router-link to="/">Home</router-link> <router-link to="/list">List</router-link> <router-link to="/about">About</router-link> <button @click="gotoAbout"> 关于 </button> </div> </template> <script setup> import { useRouter } from 'vue-router' const router = useRouter() const gotoAbout = () => { router.push('/about') } </script>
路由传参:
通过路由路径传参,在配置里面传参,如访问地址为/detail/123,详情如下
const routes= [ { path: '/detail/:id', name: 'Detail', component: Detail } ]
通过query参数传递参数:在路由跳转时使用query参数,访问地址为/detail?id=123,例如:
// 在组件中跳转 router.push({ path: '/detail', query: { id: 123 } }) // 在模板中跳转 <router-link to="/detail?id=123">Detail</router-link>
还可以使用props,meta等进行传参
嵌套路由:
嵌套路由使用配置项children
表示路由的嵌套关系,如下示例代码:
const routes = [ { path: '/', component: Home, children: [ { path: 'about', component: About }, { path: 'contact', component: Contact } ] } ]
19.vuex
创建store包,创建store/index.js 创建store对象并导出store
import { createStore } from 'vuex' export default createStore({ state: { }, mutations: { }, actions: { }, modules: { } })
state个人理解是存放全局变量的地方,mutation是可以通过函数改变state的值,mutation是同步操作,mutation的函数,在template中通过$store.commit('方法名')
触发。
异步操作在action中处理,再给mutation,action基本使用如下:
action 中定义的方法默认参数为** context
上下文**, 可以理解为 store 对象
通过 context 上下文对象,拿到store,通过 commit 触发 mution 中的方法,以此来完成异步操作。
... mutations: { sum (state, num) { state.count += num } }, actions: { // context 上下文对象,可以理解为store sum_actions (context, num) { setTimeout(() => { context.commit('sum', num) // 通过context去触发mutions中的sum }, 1000) } },
main.js引入
... import store from './store' ... app.use(store)
大概的工作模式