【Vue】- Vue核心语法


知识回顾

前言

Vue项目介绍及其核心语法

源码分析

1. 项目结构介绍(单页面应用程序)

VUE-DEMO
│─node_modules	          第三包文件夹
├─public                	放html文件的地方
| └─favicon.ico 	      	网站图标
├─src 			              源代码目录 → 以后写代码的文件夹
│  └─assets 	           	静态资源目录 → 存放图片、字体等
│  └─components         	组件目录 → 存放通用组件
│  └─App.vue   		        App根组件 → 项目运行看到的内容就在这里编写  
│  └─main.ts   		        入口文件 → 打包或运行,第一个执行的文件 
└─.eslintrc.cjs     	  	eslint配置文件
└─.gitignore     	      	git忽视文件
└─.prettierrc.json     		prettierrc配置文件
└─env.d.ts     		        ts代码智能提示使用
└─index.html          		index.html 模板文件
└─package.json		        项目配置文件 → 包含项目名、版本号、scripts、依赖包等
└─pnpm-lock.yaml 	      	pnpm锁文件,由pnpm自动生成的,锁定安装版本
└─README.md 	          	项目说明文档
└─tsconfig.app.json     	ts项目配置文件
└─tsconfig.json 	      	ts配置文件
└─tsconfig.app.json     	ts的node环境配置文件
└─vite.config.js 		      create-vue配置文件

2. 项目运行流程图(单页面应用程序)

在这里插入图片描述

项目运行后执行main.ts
main.ts中会执行app.vue文件,导入createapp方法,导入app.vue , 创建app实例对象
最后渲染到index.html容器中

3. 选项式和组合式api

  • 选项式
<template>
  <button @click="toggle">显示隐藏图片</button>
  <img v-show="show" alt="Vue logo" src="./assets/logo.png" />
  <hr />
  计数器:{{ count }} <button @click="increment">累加</button>
</template>
<script>
export default {
  data() {
    return {
      show: true,
      count: 0
    }
  },
  methods: {
    toggle() {
      this.show = !this.show
    },
    increment() {
      this.count++
    }
  }
}
</script>


  • 组合式
<template>
  <button @click="toggle">显示隐藏图片</button>
  <img v-show="show" alt="Vue logo" src="./assets/logo.svg" />
  <hr />
  计数器:{{ count }} <button @click="increment">累加</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const show = ref(true)
const toggle = () => {
  show.value = !show.value
}
const count = ref(0)
const increment = () => {
  count.value++
}
</script>


4. 插值表达式 {{}} 胡子语法

插值表达式是一种Vue的模板语法, 我们可以用插值表达式渲染出Vue提供的数据

  • 作用:利用表达式进行插值,渲染到页面中
  • 表达式:是可以被求值的代码,JS引擎会讲其计算出一个结果

注意事项:

  1. 在插值表达式中使用的数据 必须在setup函数中进行了提供
  2. 支持的是表达式,而非语句,比如:if for …
  3. 不能在标签属性中使用 {{ }} 插值 (插值表达式只能标签中间使用)
<template>
  <div>{{ title }}</div>
  <div>{{ sum(100, 200) }}</div>
  <p>{{ array[1] }}</p>
</template>

<script setup lang="ts">
const title = 'test'
const sum = (num1: number, num2: number) => {
  return num1 + num2
}
const array = [1, 2, 3]
</script>

5. reactive函数

<template>
  <button @click="onClick">点击我</button>
  <button @click="addAge">增加年龄</button>
  <button @click="addHobbies">新增爱好</button>
</template>

<script setup lang="ts">
import { reactive } from 'vue'
const person = reactive({
  name: '张三',
  age: 18,
  friend: {
    name: '李四',
    age: 20,
    hobbies: ['打游戏', '看电影']
  }
})
const onClick = () => {
  console.log('点击了')
  alert('点击了我')
}
const addAge = () => {
  person.age++
  console.log(person.age)
}
const addHobbies = () => {
  person.friend.hobbies.push('看书')
  console.log(person.friend.hobbies)
}
</script>

6. ref表达式

<template>
  <div>年龄{{ age }}</div>
  <button @click="changeAge">修改年龄</button>
  <div>{{ person }}</div>
  <button @click="changePersonAge">修改person中年龄</button>
</template>

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

const age = ref(18)
const changeAge = () => {
  age.value++
}
const person = ref({ name: '张三', age: 18 })
const changePersonAge = () => {
  person.value.age++
}
</script>

7. vue中常用指令

Vue 提供的带有 v- 前缀 的 特殊 标签属性

  • v-text v-html
  • v-if v-show
<script setup lang="ts">
import { ref } from 'vue'

const flag = ref(false)
const toggle = () => {
  flag.value = !flag.value
}
</script>


<template>
  <div v-show="flag" class="box">我是v-show控制的盒子</div>
  <div v-if="flag" class="box">我是v-if控制的盒子</div>
  <button @click="toggle">显示/隐藏</button>
</template>

<style>
.box {
  width: 100px;
  height: 100px;
  background-color: red;
  margin-bottom: 20px;
}
</style>
  • v-else 和 v-else-if
<script setup lang="ts">
import { ref } from 'vue'

// 1. 性别
const gender = ref(0) // 0-男 1-女 
// 2. 成绩
const score = ref(95)
</script>


<template>
  <div id="app">
    <p v-if="gender === 0">性别:♂ 男</p>
    <p v-else>性别:♀ 女</p>
    <hr>
    <p v-if="score >= 90">成绩评定A:奖励电脑一台</p>
    <p v-else-if="score >= 80">成绩评定B:奖励周末郊游</p>
    <p v-else-if="score >= 60">成绩评定C:奖励零食礼包</p>
    <p v-else>成绩评定D:惩罚一周不能玩手机</p>
  </div>
</template>
  • 事件绑定
<template>
  <div>
    <button @click="count--">-</button>
    <span>{{ count }}</span>
    <button v-on:click="count++">+</button>
    <p></p>
    <div class="box">
      <h3>黑马自动售货机</h3>
      <button @click="buy(5)">可乐5</button>
      <button @click="buy(10)">咖啡10</button>
      <button @click="buy(8)">牛奶8</button>
    </div>
    <p>银行卡余额:{{ money }}</p>
  </div>
</template>

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

const count = ref(100)
const money = ref(100)
const buy = (price: number) => {
  money.value -= price
}
</script>
<style></style>

8. 事件绑定获取事件对象

<template>
  <div>
    <button @click="count--">-</button>
    <span>{{ count }}</span>
    <button v-on:click="count++">+</button>
    <button @click="clickMe">点击了我</button>
    <button @click="clickMeTwo(100, $event)">点击了我</button>
    <p></p>
    <div class="box">
      <h3>黑马自动售货机</h3>
      <button @click="buy(5)">可乐5</button>
      <button @click="buy(10)">咖啡10</button>
      <button @click="buy(8)">牛奶8</button>
    </div>
    <p>银行卡余额:{{ money }}</p>
  </div>
</template>

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

const count = ref(100)
const money = ref(100)
const buy = (price: number) => {
  money.value -= price
}
const clickMe = (event: Event) => {
  console.log(event)
}
const clickMeTwo = (num: number, event: Event) => {
  console.log(num)
  console.log(event)
}
</script>
<style></style>

9. v-for遍历

Vue 提供了 v-for 列表渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。
v-for 指令需要使用 (item, index) in arr 形式的特殊语法,其中:
● item 是数组中的每一项
● index 是每一项的索引,不需要可以省略
● arr 是被遍历的数组
v-for中的key:
● 语法: key=“唯一值”
● 作用:给列表项添加的唯一标识。便于Vue进行列表项的正确排序复用。
● 为什么加key:Vue 的默认行为会尝试原地修改元素(就地复用)

<template>
  <div id="app">
    <div class="box">
      <span
        v-for="(item, index) in array"
        :key="index"
        :class="{ active: item === array[activeIndex] }"
        @click="activeIndex = index"
        >{{ item }}</span
      >
      <!-- 列表遍历 -->
      <ul>
        <li v-for="item in goods" :key="item.id">{{ item.name }}</li>
      </ul>
    </div>
  </div>
</template>

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

const array = ['首页', '内容', '我的']
const goods = [
  { name: 'apple', id: 1 },
  { name: 'banana', id: 2 },
  { name: 'orange', id: 3 },
  { name: 'pear', id: 4 }
]
const activeIndex = ref(0)
</script>

<style></style>
<style>
.box {
  display: flex;
}
.box span {
  width: 50px;
  height: 60px;
}
.active {
  background-color: red;
}
</style>

10. 遍历对象和删除

  • {{ key }} : {{ value }}

{{ item }}

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

const list = ref([
  { id: 1, name: '《红楼梦》', author: '曹雪芹' },
  { id: 2, name: '《西游记》', author: '吴承恩' },
  { id: 3, name: '《水浒传》', author: '施耐庵' },
  { id: 4, name: '《三国演义》', author: '罗贯中' }
])
const del = (id: number) => {
  // console.log('删除', id)
  // 通过 id 进行删除数组中的 对应项 → filter(不会改变原数组)
  // filter: 根据条件,保留满足条件的对应项,得到一个新数组。
  // console.log(list.value.filter(item => item.id !== id))
  list.value = list.value.filter((item) => item.id !== id)
}
</script>

<template>
  <div id="app">
    <h3>小黑的书架</h3>
    <ul>
      <li v-for="item in list" :key="item.id">
        <span>{{ item.name }}</span>
        <span></span>
        <button @click="del(item.id)">删除</button>
      </li>
    </ul>
  </div>
</template>

<style></style>

11. 双向绑定指令

所谓双向绑定就是:
● 数据改变后,呈现的页面结果会更新
● 页面结果更新后,数据也会随之而变
作用: 给表单元素(input、radio、select)使用,双向绑定数据,可以快速 获取 或 设置 表单元素内容
语法:v-model=“变量”

v-model 双向绑定的底层逻辑是 在input组件上是 value属性和input事件的结合

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

const username = ref('')
const password = ref('')
const onChange = (event: Event) => {
  username.value = (event.target as HTMLInputElement).value
  console.log(username.value)
}
const login = () => {
  console.log(username.value, password.value)
}
const reset = () => {
  username.value = ''
  password.value = ''
}
</script>

<template>
  <div id="app">
    <!-- 账户:<input v-model="username" type="text" /> <br /><br /> -->
    <!-- v-model的底层逻辑写法 -->
    <!--底层逻辑是value属性和input事件的结合 -->
    账户:<input :value="username" type="text" @input="onChange" /> <br /><br />
    密码:<input v-model="password" type="password" /> <br /><br />
    <button @click="login">登录</button>
    <button @click="reset">重置</button>
  </div>
</template>

<style></style>


12. 计算属性

  1. 概念
    ● 基于现有的数据,计算出来的新属性。 依赖的数据变化,自动重新计算。

  2. 语法
    ● 声明在 computed 函数中,一个计算属性对应一个函数
    ● 使用起来和普通属性一样使用 {{ 计算属性名}}
    ● computed中的计算属性虽然是函数的写法,但它依然是个属性

  3. 使用步骤
    ● 从 vue 中导出 computed 函数
    ● 在 setup 函数中,使用 computed 函数,传入一个函数,函数返回计算好的数据

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

const list = ref([
  { id: 1, name: '篮球', num: 1 },
  { id: 2, name: '玩具', num: 2 },
  { id: 3, name: '铅笔', num: 5 }
])

// 使用计算属性,有缓存只执行一次,后面的取缓存数值
const total = computed(() => {
  return list.value.reduce((sum, item) => sum + item.num, 0)
})

// 使用函数没有缓存
const totalNum = () => {
  return list.value.reduce((sum, item) => sum + item.num, 0)
}
</script>

<template>
  <div id="app">
    <h3>小黑的礼物清单</h3>
    <table>
      <tr>
        <th>名字</th>
        <th>数量</th>
      </tr>
      <tr v-for="item in list" :key="item.id">
        <td>{{ item.name }}</td>
        <td>{{ item.num }}</td>
      </tr>
    </table>

    <!-- 目标:统计求和,求得礼物总数 -->
    <p>礼物总数:{{ total }}</p>
  </div>
</template>

<style>
table {
  border: 1px solid #000;
  text-align: center;
  width: 240px;
}

th,
td {
  border: 1px solid #000;
}

h3 {
  position: relative;
}
</style>

13. 侦听器

  1. 作用
    ● 监视数据变化,执行一些业务逻辑或异步操作
  1. 主要使用方式
    ● 使用 watch 监听一个响应式数据 watch(数据, 改变后回调函数)
    ● 使用 watch 监听多个响应式数据 watch([数据1, 数据2, …], 改变后回调函数)
    ● 使用 watch 监听响应式对象数据中的一个属性(简单) watch(()=>数据, 改变后回调函数)
    ● 使用 watch 监听响应式对象数据中的一个属性(复杂),配置深度监听
    ● 使用 watch 监听,配置默认执行
一个和多个响应数据变化
<script setup lang="ts">
import { reactive, ref, watch } from 'vue'

// 1. 使用 watch 监听一个响应式数据
const count = ref(100)
// 只监听一个
// watch(count, (newValue, oldValue) => {
//   console.log(newValue, oldValue)
// })

const user = reactive({
  name: 'tom',
  info: {
    gender: '男',
    age: 18
  }
})
// 监听两个
watch([count, user], (newValue, oldValue) => {
  console.log(newValue, oldValue)
})

// 2s后count加一
setTimeout(() => {
  count.value++
}, 2000)

// 4s后user.info.age加一
setTimeout(() => {
  user.info.age++
}, 4000)
</script>

<template>
  <div class="app-page">
    <div>{{ count }}</div>
    <button @click="count++"></button>
  </div>
</template>

<style lang="css" scoped></style>


深度监听
<script setup lang="ts">
import { reactive, ref, watch } from 'vue'

// 1. 使用 watch 监听一个响应式数据
const count = ref(100)
// 只监听一个
// watch(count, (newValue, oldValue) => {
//   console.log(newValue, oldValue)
// })

const user = reactive({
  name: 'tom',
  info: {
    gender: '男',
    age: 18
  }
})
// 监听两个
watch([count, user], (newValue, oldValue) => {
  console.log(newValue, oldValue)
})

// 2s后count加一
setTimeout(() => {
  count.value++
}, 2000)

// 4s后user.info.age加一
setTimeout(() => {
  user.info.age++
}, 4000)

// 3. 监听响应式对象数据的一个数据,简单类型
// watch(()=>数据, 改变后回调函数)
watch(
  () => user.info.age,
  (newValue, oldValue) => {
    console.log(newValue, oldValue)
  }
)

// 深度监听deep:true
watch(
  () => user.info,
  (newValue) => {
    console.log(newValue)
  },
  { deep: true }
)
// 新版已经不需要设置,直接对其进行监听不需要箭头函数
watch(user.info, (newValue) => {
  console.log(newValue)
})
</script>

<template>
  <div class="app-page">
    <div>{{ count }}</div>
    <button @click="count++"></button>

    <p>姓名:{{ user.name }} 性别:{{ user.info.gender }} 年龄:{{ user.info.age }}</p>
  </div>
</template>

<style lang="css" scoped></style>

  1. 小结
    ● watch(需要监听的数据,数据改变执行函数,配置对象) 来进行数据的侦听
    ● 数据:单个数据,多个数据,函数返回对象属性,属性复杂需要开启深度监听
    ● 配置对象:deep 深度监听 immediate 默认执行

拓展知识

reactive和ref的选择

  1. 开始分析
    ● reactive 可以转换对象成为响应式数据对象,但是不支持简单数据类型。
    ● ref 可以转换简单数据类型为响应式数据对象,也支持复杂数据类型,但是操作的时候需要 .value 。
    ● 它们各有特点,现在也没有最佳实践,没有明显的界限,所有大家可以自由选择。
  2. 推荐用法
    ● 如果能确定数据是对象且字段名称也确定,可使用 reactive 转成响应式数据,其他一概使用 ref 。这样就没有心智负担 。

总结

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值