vue3.0初窥

it2024-12-18  11

vite构建demo

优点

1.基于浏览器原生ES imports 的开发服务器(利用浏览器去解析imports,在服务器端按需编译返回,完全跳过了打包这个概念,服务器随起随用)

2.同时不仅有Vue文件支持,还支持热更新,而且热更新的速度不会随着模块增多而变慢

构建指令

npm init vite-app name cd name npm run dev/build

与cli的不同点

1.html页面没放在public下了,挪到了根目录下

2.vite构建是将所有的代码都放在页面模板里面的一个type=module的script标签中

<script type="module" src="/src/main.js"></script>

3.在这个script标签中间,可以直接通过import的方式引用,而不需要像webpack那样先进行打包编译了

Composition Api  (响应式系统Api)

官方文档

setup

概念

setup函数是一个新的的组件选项,作为在组件内使用Composition Api的入口点

特性

1.在初始化props和beforeCreated之前调用 2.接收props和context两个参数

props 父组件传进来的基于Proxy代理的响应式数据,和vue2.0的也差不多context 可以拿到一些属性像attrs、slots、emit 3.this在setup里面不可用 4.只会在初次加载是执行一次,数据变更不会再次执行 5.如果setup返回一个对象,则对象的属性可以在模板中进行渲染

组合式api

使用之前需要从vue导出来

import {  watchEffect, computed, reactive, readonly, ref, watch } from 'vue'
ref

将单个简单值构建为响应式对象,在setup里使用时,要名字.value的方式操作,在标签中使用可以直接用名称

<template>   <div>     <p>支持人数:{{ supNum }}</p>     <p>反对人数:{{ oppNum }}</p>     <p>支持率:{{ ratio }}</p>     <button @click="change(0)">支持</button>     <button @click="change(1)">反对</button>   </div> </template> <script> import { ref } from 'vue' export default {   setup (props, context) {     let supNum = ref(0) // ref的括号里面包裹初始值value     let oppNum = ref(0)     let ratio = ref(0)     function change (type) {       type ? oppNum.value++ : supNum.value++       let total = oppNum.value + supNum.value       ratio.value = (((supNum.value / total) * 100).toFixed(2)) + '%'     }     return {       supNum, oppNum, ratio, change     }   } } </script>
reactive

1.将复杂值构建为响应式对象,有点像vue2.0的data,里面的值都是响应式的

2.在setup里使用要以对象的形式使用,在模板使用可以在导出时,先用toRefs把响应式对象转换为普通对象,让每个属性都是一个ref,再解耦导出

<template>   <div>     <p>支持人数:{{ supNum }}</p>     <p>反对人数:{{ oppNum }}</p>     <p>支持率:{{ ratio }}</p>     <button @click="change(0)">支持</button>     <button @click="change(1)">反对</button>   </div> </template> <script> import { reactive, ref, toRefs } from 'vue' export default {   setup (props, context) {     let state = reactive({       supNum: 0,       oppNum: 0,       ratio: 0,     })     function change (type) {       type ? state.oppNum++ : state.supNum++       let total = state.oppNum + state.supNum       state.ratio = (((state.supNum / total) * 100).toFixed(2)) + '%'     }     return {       // 为了可以直接在模板渲染时直接用,先解耦       // 导出的时候,要把响应式对象转换成普通对象,但每个属性都是一个ref       ...toRefs(state),       change     }   } } </script>
readonly

传入一个对象(响应式或普通)或 ref,返回一个原始对象的只读代理(所有层级所有属性都是只读),在代码中再修改这个对象或ref,都会报提示,可以用来设置一些不允许修改,但很多组件都要用到的公共数据

<template>   <div>     <p>支持人数:{{ supNum }}</p>     <p>反对人数:{{ oppNum }}</p>     <p>支持率:{{ ratio }}</p>     <button @click="change(0)">支持</button>     <button @click="change(1)">反对</button>   </div> </template> <script> import { reactive, readonly, ref, toRefs } from 'vue' export default {   setup (props, context) {     // 把state设置为只读     let state = readonly(       // 创建一个响应式对象       reactive({         supNum: 0,         oppNum: 0,         ratio: 0,       })     )     function change (type) {       type ? state.oppNum++ : state.supNum++       let total = state.oppNum + state.supNum       state.ratio = (((state.supNum / total) * 100).toFixed(2)) + '%'     }     return {       // 为了可以直接在模板渲染时直接用,先解耦       // 导出的时候,要把响应式对象转换成普通对象,但每个属性都是一个ref       ...toRefs(state),       change     }   } } </script>

点击按钮的话,会报这是只读属性

computed

1.传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象,直接name.value++就会报错,感觉vue2.0也差不多

<template>   <div>     <p>支持人数:{{ supNum }}</p>     <p>反对人数:{{ oppNum }}</p>     <p>支持率:{{ ratio }}</p>     <button @click="change(0)">支持</button>     <button @click="change(1)">反对</button>   </div> </template> <script> import { computed, reactive, readonly, ref, toRefs } from 'vue' export default {   setup (props, context) {     // 创建一个响应式对象     let state = reactive({       supNum: 0,       oppNum: 0,     })     // 传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象。     let ratio = computed(() => {       let total = state.oppNum + state.supNum       return total > 0 ? ((state.supNum / total) * 100).toFixed(2) + '%' : '--'     })     ratio.value++ // 这样会报错     function change (type) {       type ? state.oppNum++ : state.supNum++     }     return {       // 为了可以直接在模板渲染时直接用,先解耦       // 导出的时候,要把响应式对象转换成普通对象,但每个属性都是一个ref       ...toRefs(state),       ratio,       change     }   } } </script>

2.或者传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态,这种用的少

// 传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态。 let ratio = computed({   get: () => {     let total = state.oppNum + state.supNum     return total > 0 ? ((state.supNum / total) * 100).toFixed(2) + '%' : '--'   },   set: (val) => {     console.log(val);   } }) ratio.value++ //  这样会执行computed的set函数
watchEffect

1.立即执行传入的一个函数,就是一进来就会执行一次

2.并响应式追踪其依赖,就是在它里面用到了的变量修改了都会执行这个方法,它里面打印了的变量修改了也会执行这个方法

<template>   <div>     <p>支持人数:{{ supNum }}</p>     <p>反对人数:{{ oppNum }}</p>     <p>支持率:{{ ratio }}</p>     <button @click="change(0)">支持</button>     <button @click="change(1)">反对</button>   </div> </template> <script> import { watchEffect, computed, reactive, readonly, ref, toRefs } from 'vue' export default {   setup (props, context) {     // 创建一个响应式对象     let state = reactive({       supNum: 0,       oppNum: 0,       ratio: 0     })     // 立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数     watchEffect(() => {       console.log(state.supNum, 'state.supNum', state.oppNum) //打印了的变量修改了也会执行        let total = state.oppNum + state.supNum //用到了的变量修改了都会执行这个方法       state.ratio = total > 0 ? ((state.supNum / total) * 100).toFixed(2) + '%' : '--'     })     function change (type) {       type ? state.oppNum++ : state.supNum++     }     return {       // 为了可以直接在模板渲染时直接用,先解耦       // 导出的时候,要把响应式对象转换成普通对象,但每个属性都是一个ref       ...toRefs(state),       change     }   } } </script>
watch

1.watch API 完全等效于vue2.x的watch。侦听指定的变量,变量修改执行回调

2.它可以监听响应式对象和ref,第一个参数放监听对象,但如果是监听响应式对象里面具体的一个属性,需要写成函数的返回该属性的形式,第二个参数是回调函数,第三个参数是配置immediate立即执行和deep深度监听都有

// 监听对象 watch(state,   (val, oldVal) => {     console.log(val, oldVal, 'val,oldVal')   },   {     immediate: true,     deep: true   }) // 监听对象中的属性 watch(()=>state.supNum, (val, oldVal) => {   console.log(val, oldVal, 'val,oldVal') })

3.可以将多个变量用一个watch进行监控,只要它监控的变量里面任意一个发生改变都会执行回调用,具体就是将原来的单个参数改为数组,放多个参数

// 将多个变量用一个watch进行监控,只要它监控的变量里面任意一个发生改变都会执行回调用 watch([() => state.supNum, () => state.oppNum], ([val, val2], [oldVal, oldVal2]) => {   console.log([val, val2], [oldVal, oldVal2], '[val, val2], [oldVal, oldVal2]') })

响应式系统工具集

总共七个,基本上从字面上看就可以判断出功能,都是用于类型判断和类型转换

import { isProxy, isReactive, isReadonly, isRef, toRef, toRefs, unref } from 'vue'

unref 如果参数是一个 ref 则返回它的 value,否则返回参数本身

toRef、toRefs,一个是将reactive对象的属性创建一个ref,一个是统一处理,将reactive对象的每一个属性创建为个ref

3.isProxy、isReactive、isReadonly、isRef判断是否是各自名称对应的类型,返回布尔值

生命周期钩子函数

1.基本上与之前vue2.x的类似,只是需要从vue导入,并且在setup中以on钩子名的方式调用

import { onMounted, onUpdated, onUnmounted } from 'vue' const MyComponent = {   setup() {     onMounted(() => {       console.log('mounted!')     })     onUpdated(() => {       console.log('updated!')     })     onUnmounted(() => {       console.log('unmounted!')     })   }, } vue2.x和vue3.0名称对应关系

依赖注入

provide 和 inject 提供依赖注入,功能类似 2.x 的 provide/inject。两者都只能在当前活动组件实例的 setup() 中调用。

import { provide, inject } from 'vue' const ThemeSymbol = Symbol() const Ancestor = {   setup() {     provide(ThemeSymbol, 'dark')   }, } const Descendent = {   setup() {     const theme = inject(ThemeSymbol, 'light' /* optional default value */)     return {       theme,     }   }, }

模板Refs

当使用组合式 API 时,reactive refs 和 template refs 的概念已经是统一的。为了获得对模板内元素或组件实例的引用,我们可以像往常一样在 setup() 中声明一个 ref 并返回它:

<template>   <div ref="root"></div> </template> <script>   import { ref, onMounted } from 'vue'   export default {     setup() {       const root = ref(null)       onMounted(() => {         // 在渲染完成后, 这个 div DOM 会被赋值给 root ref 对象         console.log(root.value) // <div/>       })       return {         root,       }     },   } </script>

使用vue脚手架

1.cli版本需要大于4.0

2.选择配置

3.选择vue版本

4.安装axios和ui框架Ant Design of Vue2.x版本

cnpm install axios ant-design-vue --save

5.main.js入口文件

// 入口文件 // 和2.0不一样的地方,导出了createApp import { createApp } from 'vue' import App from './App.vue' import './registerServiceWorker' import router from './router' import store from './store' // vue3都是函数,通过函数的方式去创建和挂载 createApp(App).use(store).use(router).mount('#app')

创建和挂载这里可以改成和vue2.0像一点的方式

const vue  =  createApp(App) vue.use(store) vue.use(router) vue.mount('#app')

6.app.vue

<template>   <a-layout id="components-layout-demo-fixed">     <a-layout-header :style="{ position: 'fixed', zIndex: 1, width: '100%' }">       <div class="logo" />       <!-- v-model:selectedKeys="selectedKeys"表示传了两个属性,       一个叫value,一个叫selecteKeys -->       <a-menu         theme="dark"         mode="horizontal"         v-model:selectedKeys="selectedKeys"         :style="{ lineHeight: '64px' }"       >         <a-menu-item key="/">           <router-link to="/">首页</router-link>         </a-menu-item>         <a-menu-item key="/plan">           <router-link to="/plan">时间计划</router-link>         </a-menu-item>       </a-menu>     </a-layout-header>     <a-layout-content :style="{ padding: '0 50px', marginTop: '64px' }">       <a-breadcrumb :style="{ margin: '16px 0' }"> </a-breadcrumb>       <div :style="{ background: '#fff', padding: '24px', minHeight: '380px' }">         <router-view></router-view>       </div>     </a-layout-content>     <a-layout-footer :style="{ textAlign: 'center' }">       Ant Design ©2018 Created by Ant UED     </a-layout-footer>   </a-layout> </template> <script> // 需要在开始把要用到的方法引入进来 //       挂载钩子            监控   双向绑定用的reactive方法 import { onMounted, toRefs, ref, watch, reactive, computed } from 'vue' import { useRoute } from 'vue-router' import { useStore } from 'vuex' // vue3使用的是函数式api,做混入更方便 export default {   // 入口函数,默认只执行一次,可以在入参里拿到属性和上下文,我们可以把所有的逻辑都放到setup里,比较好管理   setup (props, context) { // context里面可以拿到一些属性像attrs、slots、emit     // 执行vuex方法     const store = useStore()     // 执行路由方法     const route = useRoute()     //使用reactive方法创建响应式数据     const state = reactive({       // 计算属性        selectedKeys: computed(() => {         return [route.path]       }),       // 单独将某个属性变成响应式的       allTime: ref(store.getters.allTime)     })     /**      * @description: 监控某个属性      * @param {type} 一个拥有返回值的 getter 函数,也可以是 ref      * @param {type} 回调,参数和vue2一样      * @param {type} 对象,参数配置,和vue2一样      * @author: dlb      */     // watch(() => route.path, (newValue, oldValue) => {     //   console.log(newValue, 'newValue')     //   state.selectedKeys = [newValue]     // }, {     //   immediate: true,     //   deep: true     // })     // 新的写法所有的钩子都是函数     onMounted(() => {       console.log('mounted!')     })     // 如果 setup 返回一个对象,则对象的属性将会被合并到组件模板的渲染上下文     return {       // 将响应式数据state返回       // toRef 可以用来为一个 reactive 对象的属性创建一个 ref。这个 ref 可以被传递并且能够保持响应性。       ...toRefs(state),     }     // 这里如果返回的时函数,return的内容会覆盖掉template的内容     // return ()=>{     //   return <h1>998</h1>     // }   }, }; </script> <style> #components-layout-demo-fixed .logo {   width: 120px;   height: 31px;   background: rgba(255, 255, 255, 0.2);   margin: 16px 24px 16px 0;   float: left; } </style>

vue3.0废弃了过滤器,可用函数替代

api请求环境控制(根据不同的环境,获取不同的路径)

1.在vue项目的根目录上创建以".env.环境 "命名的文件,例入开发:.env.development

2.在运行开发或者构建命令时,它默认会自动的去读这个文件的变量,这个变量必需以VUE_APP_开头,后面可以用自己定义的变量,例如:VUE_APP_URL

VUE_APP_URL='http://192.168.3.43:9527'

3.获取时,在任意文件里用 process.env.都可以直接去取以VUE_APP_开头的变量,例如process.env.VUE_APP_URL

3.文件的读取有优先级,默认是先读.env文件,如果没有的话,再读.env.development

最新回复(0)