学习vue 九 nextTick 函数式编程 编译宏 环境变量

nextTick

js事件循环机制

所有的同步任务都是在主进程执行的形成一个执行栈,主线程之外,还存在一个"任务队列",异步任务执行队列中先执行宏任务,然后清空当次宏任务中的所有微任务,然后进行下一个tick如此形成循环。

nextTick 就是创建一个异步任务,那么它自然要等到同步任务执行完成后才执行。

案例:

写一个聊天框要求在每次发送完新的信息之后,导航条滑到最低端

<template>
  <div ref="box" class="wraps">
    <div>
      <div class="item" v-for="item in chatList">
        <div>{{ item.name }}:</div>
        <div>{{ item.message }}</div>
      </div>
    </div>
  </div>
  <div class="ipt">
    <div>
      <textarea v-model="ipt" type="text" />
    </div>
    <div>
      <button @click="send">send</button>
    </div>
  </div>
  <HelloWorld></HelloWorld>
</template>

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

let chatList = reactive([
  { name: '张三', message: "xxxxxxxxx" },
])
let box = ref<HTMLDivElement>()
let ipt = ref('')
//Vue 更新dom是异步的 数据更新是同步
//我们本次执行的代码是同步代码
//当我们操作dom 的时候发现数据读取的是上次的 就需要使用nextIick
const send = async () => {
  chatList.push({
    name:"李四",
    message:ipt.value
  })
  //1.回调函数模式
  // nextTick(() => {
  //   box.value!.scrollTop = 99999999
  // })
  //2.async await 写法 await以下全部为异步代码
  await nextTick()
  box.value!.scrollTop = 99999999
}
</script>

<style scoped>
.wraps {
  margin: 10px auto;
  width: 500px;
  height: 400px;
  overflow: auto;
  overflow-x: hidden;
  background: #fff;
  border: 1px solid #ccc;
}
.wraps .item {
  width: 100%;
  height: 50px;
  background: #ccc;
  display: flex;
  align-items: center;
  padding: 0 10px;
  border-bottom: 1px solid #fff;
}

.ipt {
  margin: 10px auto;
  width: 500px;
  height: 40px;
  background: #fff;
  border: 1px solid #ccc;
}
.ipt textarea {
  width: 100%;
  height: 100%;
  border: none;
  outline: none;
}
.ipt button {
  width: 100px;
  margin: 10px 0;
  float: right;
}
</style>

函数式编程

主要使用h函数去写模板,为什么要使用h函数,因为h函数会直接调用createVNode函数,生成虚拟dom性能上面会有所提升

h函数接受三个参数

  • type 元素的类型
  • propsOrChildren 数据对象, 这里主要表示(props, attrs, dom props, class 和 style)
  • children 子节点

案例:

定义一个按钮

<script setup lang='ts'>
import { ref,h } from 'vue'
const fs = ref("16px")
const tableRef = ref([
  { name: '张三', age: 18, gender: '男' },
  { name: '李四', age: 20, gender: '女' },
  { name: '王五', age: 22, gender: '男' },
  { name: '赵六', age: 24, gender: '女' },
])
type Props = {
  text: string
}
const Btn = (props:Props,ctx:any) => {
  return h("button",{
    style:{
      width:"100px",
      height:"30px",
      fontSize:fs.value,
    },
    onClick:()=>{
      console.log("按钮被点击了")
      console.log(props.text)
    }
  },ctx.slots.default())
}
</script>

<template>
  <div class="btn">
    <button @click="fs = '15px'">小</button>
    <button @click="fs = '20px'">中</button>
    <button @click="fs = '22px'">大</button>
  </div>
 <table border="1">
   <thead>
     <tr>
       <th>姓名</th>
       <th>年龄</th>
       <th>性别</th>
       <th>操作</th>
     </tr>
   </thead>
   <tbody>
     <tr v-for="item in tableRef" :key="item.name">
       <td>{{ item.name }}</td>
       <td>{{ item.age }}</td>
       <td>{{ item.gender }}</td>
       <td>
         <Btn text="这是要被传入props的">编辑</Btn>
         <Btn>删除</Btn>
       </td>
     </tr>
   </tbody>
 </table>
</template>

<style scoped>
.btn {
  width: 50%;
  margin: 0 auto;
}
.btn button {
  margin: 0 10px;
  padding: 5px 10px;
  font-size: 16px;
  border: 1px solid #ccc;
  border-radius: 5px;
  cursor: pointer;
}
table {
  width: 50%;
  margin: 20px auto;
  border-collapse: collapse;
  font-size: v-bind(fs);
  text-align: center;
}
</style>

编译宏

Vue 3.3新增了一些语法糖和宏,包括泛型组件、defineSlots、defineEmits、defineOptions

defineProps

父子组件传参

案例:

父组件

<script setup lang='ts'>
import { ref } from 'vue'
import B from './components/B.vue'
const text = ref('hello')
</script>

<template>
  <B :text="text"></B>
</template>

<style scoped>

</style>

子组件

<script setup lang="ts">
const props = defineProps<{
  text: string
}>()
console.log(props.text)
</script>

<template>
  <h1>{{text}}</h1>
</template>

<style scoped>

</style>

vue3.3 新增可以给defineProps增加一个泛型

<script setup generic="T" lang="ts">
const props = defineProps<{
  text: T[]
}>()
console.log(props.text)
</script>

<template>
  <h1>{{text}}</h1>
</template>

<style scoped>

</style>

这样的话,text的类型就更加的灵活

defineEmits

父组件

<script setup lang='ts'>
import { ref } from 'vue'
import B from './components/B.vue'
const text = ref([1, 2, 3])
function handleEmit(data: any) {
    console.log(data)
}
</script>

<template>
  <B :text="text" @change="handleEmit"></B>
</template>

<style scoped>

</style>

子组件常规方法派发事件

<script setup generic="T" lang="ts">
import {onMounted} from "vue";
const props = defineProps<{
  text: T[]
}>()
const emit = defineEmits<{
  (e: 'change', value: string): void
}>()
onMounted(() => {
  emit('change',"我已经传值")
})
console.log(props.text)
</script>

<template>
  <h1>{{text}}</h1>
</template>

<style scoped>

</style>

Vue3.3 新写法更简短

<script setup generic="T" lang="ts">
import {onMounted} from "vue";
const props = defineProps<{
  text: T[]
}>()
const emit = defineEmits<{
  change: [string]
}>()
onMounted(() => {
  emit('change',"我已经传值")
})
console.log(props.text)
</script>

<template>
  <h1>{{text}}</h1>
</template>

<style scoped>

</style>

环境变量

环境变量:他的主要作用就是让开发者区分不同的运行环境,来实现 兼容开发和生产

例如 npm run dev 就是开发环境  npm run build 就是生产环境等等

Vite 在一个特殊的 import.meta.env 对象上暴露环境变量。这里有一些在所有情况下都可以使用的内建变量

  1. BASE_URL: "/"
  2. DEV: true
  3. MODE: "development"
  4. PROD: false
  5. SSR: false

注意:环境变量不能通过变量的形式添加或者修改即: import.meta.env[mode] = xxx 

因为这些环境变量在打包的时候是通过硬编码通过Json.stringify的方式注入到浏览器的

配置额外的环境变量 

在开发环境中:

1. 在更目录下创建文件.env.development

 

 2. 修改启动命令

在 package json 配置 --mode env文件名称

 

 这样就配置完成,可以在env上看到了

 

在生产环境中

创建 .env.production  在执行npm run build 的时候他会自己加载这个文件 

在文件中写入配置的变量即可 

  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值