Vue的基础知识

模板语法

符号名称说明
{{ }}文本插值大括号中放变量,页面会随变量的值响应式变化
v-html 原始HTML变量的值会被当做HTML处理
v-bind 属性绑定给标签的属性绑定一个变量,简写 :属性名=“属性值变量” 特别的:属性名除了可以是常量,还可以是变量,为了区分常量和变量,对应的变量需要放在【】中 :<a v-bind:[attributeName]="url"> ...</a>
v-on 事件绑定@事件名 简写
v-if v-else-if v-else条件渲染DOM元素根据不同的条件渲染不同的DOM 元素不会频繁改变考虑使用他 可以直接作用在<template> </template>
v-show 是否展示 DOM元素DOM元素都会被渲染,通过修改display属性来到达最后的效果 如果对应的DOM元素频繁改变,考虑使用它 (但有更高的初始渲染开销)
v-for列表渲染作用的对象是 数组,对象,数字 支持解构赋值
.修饰符修饰符用来表示一些特殊的行为在这里插入图片描述

响应式基础

响应式对象

Vue可以跟踪对象的属性的改变,改变页面的值
本质就是JavaScript Proxy对象(代理对象)

reactive() 声明响应式状态
import { reactive } from 'vue'
const state = reactive({ count: 0 })
  • 搭配setup()函数使用,返回对应的值
import { reactive } from 'vue'

export default {
  setup() {
    const state = reactive({ count: 0 })

    function increment() {
      state.count++
    }

    // 不要忘记同时暴露 increment 函数
    return {
      state,
      increment
    }
  }
}
两种方式暴露数据的方式
  1. setup()函数 return数据
  2. 直接在<script setup>中声明
<script setup>
import { reactive } from 'vue'

const state = reactive({ count: 0 })

function increment() {
  state.count++
}
</script>

<template>
  <button @click="increment">
    {{ state.count }}
  </button>
</template>

对象数据声明为响应式的必要性

  1. 响应代理对象和原始对象不是全等的,响应代理对象才有响应性
  2. 同个对象多次调用reactive()返回的是同一个对象
// 在同一个对象上调用 reactive() 会返回相同的代理
console.log(reactive(raw) === proxy) // true

// 在一个代理上调用 reactive() 会返回它自己
console.log(reactive(proxy) === proxy) // true
  1. 响应对象的属性,依然是响应代理对象,不是代理对象
const proxy = reactive({})

const raw = {}
proxy.nested = raw

console.log(proxy.nested === raw) // false
  1. reactive()的局限性
  • 仅对对象类型有效(对象、数组和 Map、Set 这样的集合类型),而对 string、number 和 boolean 这样的 原始类型 无效
  • reactive()是通过属性进行追踪,因此必须保持对该响应式对象的相同引用,防止出现替换的现象
let state = reactive({ count: 0 })

// 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)
state = reactive({ count: 1 })

// 将响应式对象的属性赋值或解构至本地变量时,或是将该属性传入一个函数时,我们会失去响应性
const state = reactive({ count: 0 })

// n 是一个局部变量,同 state.count
// 失去响应性连接
let n = state.count
// 不影响原始的 state
n++

// count 也和 state.count 失去了响应性连接
let { count } = state
// 不会影响原始的 state
count++

// 该函数接收一个普通数字,并且
// 将无法跟踪 state.count 的变化
callSomeFunction(state.count)
  1. ref()类似于值赋值代理,不会像reactive()代理,容易造成失去响应连接,ref()方法将 传入的值当做对象的 .value的属性的值
  2. ref自动解包的时机,ref变量在模板中被当做顶层属性访问,这里的顶层属性是直接对代理对象的.value操作
<script setup>
import { ref } from 'vue'

const count = ref(0) // 直接操作的响应对象的.value的值

function increment() {
  count.value++
}
</script>

<template>
  <button @click="increment">
    {{ count }} <!-- 无需 .value -->
  </button>
</template>
1.在模板中的解包
const object = { foo: ref(1) }
// 下面的表达式将不会像预期的那样工作:
{{ object.foo + 1 }}
//解构赋值 const foo = ref(1)
const { foo } = object
// 这种就是顶层属性
{{ foo + 1 }}


2. 在响应式对象中的解包:会自动解包(区别于模板中)
注意,是属性的值是ref
const count = ref(0)
const state = reactive({
  count
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1


3.数组和集合类型的ref解包:不会自动解包
注意:不是整个数组用ref,而是数组的值
const books = reactive([ref('Vue 3 Guide')])
// 这里需要 .value
console.log(books[0].value)

const map = reactive(new Map([['count', ref(0)]]))
// 这里需要 .value
console.log(map.get('count').value)

计算属性

用来解决模板中的复杂的逻辑
注意:

  1. computed 必须接收一个,getter的方法,返回的属性是ref响应式的
  2. computed的更新时机是对应的依赖的值改变时才会改变
  3. computed中的属性最好仅仅可读,不能进行修改
  4. computed函数最好仅仅用来计算和返回一些值,不要做额外的操作,如改变DOM(可以用监视器实现),相当于快照
<script setup>
import { reactive, computed } from 'vue'

const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

// 一个计算属性 ref   这是选项式
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})

//组合式
export default {
computed:{
	方法名(){
		类似于 getter方法
		}
	}
}
</script>

<template>
  <p>Has published books:</p>
  <span>{{ publishedBooksMessage }}</span>
</template>

如果对应的计算的属性需要修改

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

const firstName = ref('John')
const lastName = ref('Doe')

const fullName = computed({
  // getter
  get() {
    return firstName.value + ' ' + lastName.value
  },
  // setter
  set(newValue) {
    // 注意:我们这里使用的是解构赋值语法
    [firstName.value, lastName.value] = newValue.split(' ')
  }
})
</script>

类和样式的绑定

用来给class属性动态绑定样式名 (绑定HTML class属性)
  1. :class中通常绑定一个对象或者,数组,响应的值是对象,对象的属性为true添加class样式,数组就是将数组中的值都加入进去
  2. 在自定义的组件上用:class动态绑定,会将对应的样式添加到自定义组件的根元素
const isActive = ref(true)
const hasError = ref(false)

<div
  class="static"
  :class="{ active: isActive, 'text-danger': hasError }"
></div>
最后的效果:
<div class="static active"></div>

// 直接用对象的方式
const isActive = ref(true)
const error = ref(null)

const classObject = computed(() => ({
  active: isActive.value && !error.value,
  'text-danger': error.value && error.value.type === 'fatal'
}))
<div :class="classObject"></div>

// 数组
const activeClass = ref('active')
const errorClass = ref('text-danger')
<div :class="[activeClass, errorClass]"></div>
// 渲染的结果
<div class="active text-danger"></div>

:style 绑定内联样式
  1. 同上支持字符串拼接变量,支持对象,支持数组方式
  2. Vue会做一个自动浏览器前缀的操作,根据浏览器自动在样式前添加前缀
-webkit-transition: all 4s ease;
-moz-transition: all 4s ease;
-ms-transition: all 4s ease;
-o-transition: all 4s ease;
transition: all 4s ease;

const activeColor = ref('red')
const fontSize = ref(30)
// 前者的属性名 fontSize没有添加对应的引号,是 camelCase写法,两种等价
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
<div :style="{ 'font-size': fontSize + 'px' }"></div>

// 样式会合并
<div :style="[baseStyles, overridingStyles]"></div>

列表渲染 v-for

  1. 最后一个参数是下标
  2. 支持解构赋值
  3. 支持直接在template上使用
  4. key的作用是用来追踪元素,放在元素位置修改后出现非预期的情况
  5. 子组件使用时还需要将对应的变量单独传一遍
数组
const parentMessage = ref('Parent')
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
<li v-for="(item, index) in items">
  {{ parentMessage }} - {{ index }} - {{ item.message }}
</li>

对象
const myObject = reactive({
  title: 'How to do lists in Vue',
  author: 'Jane Doe',
  publishedAt: '2016-04-10'
})
<li v-for="(value, key, index) in myObject">
  {{ index }}. {{ key }}: {{ value }}
</li>

数字 从1 开始
<span v-for="n in 10">{{ n }}</span>

// 会将需要单独传递 props
<MyComponent
  v-for="(item, index) in items"
  :item="item"
  :index="index"
  :key="item.id"
/>

v-for 和 v-if的优先级问题
4. v-if 的优先级较高,v-if无法访问v-for的局部的变量
5. 监听数组变化,v-for会根据数组元素的变化实时变化,这里包括直接在原数组改变,【 push(),pop(),shift(),unshift(),splice(),sort(),reverse()】;还包括替换数组的情况,也有一些不可变 (immutable) 方法,例如 filter(),concat() 和 slice(),这些都不会更改原数组,而总是返回一个新数组。

// `items` 是一个数组的 ref
items.value = items.value.filter((item) => item.message.match(/Foo/))
  1. 对数组进行过滤排序操作,过滤可以使用computed的方式实现,对排序,不建议直接修改原数组,先进行对应的备份操作
7. 直接用计算属性
const numbers = ref([1, 2, 3, 4, 5])

const evenNumbers = computed(() => {
  return numbers.value.filter((n) => n % 2 === 0)
})
<li v-for="n in evenNumbers">{{ n }}</li>
8. 多层循环,对应内层的循环的数据进行处理操作
const sets = ref([
  [1, 2, 3, 4, 5],
  [6, 7, 8, 9, 10]
])

function even(numbers) {
  return numbers.filter((number) => number % 2 === 0)
}
<ul v-for="numbers in sets">
  <li v-for="n in even(numbers)">{{ n }}</li>
</ul>
9. 改变原数组的最后备份
- return numbers.reverse()
+ return [...numbers].reverse()

表单输入绑定v-model

  1. 对于一些有输入性质的DOM标签上使用,会将对应的value属性的值绑定到v-model的变量上
  2. 仅仅使用v-model绑定,对于单选按钮,复选框和选择器选项,v-model 绑定的值通常是静态的字符串 (或者对复选框是布尔值),可以结合v-bind,为对应的单选按钮,复选框和选择器选项的value属性绑定变量值
  3. v-model会忽略表单的初始值,始终有v-model变量本身的初始值决定
1. 单行文本输入框
<p>Message is: {{ message }}</p>
<input v-model="message" placeholder="edit me" />
2. 多行文本输入框
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

3. 复选框
const checkedNames = ref([])
<div>Checked names: {{ checkedNames }}</div>

<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>

<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>

<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>

4.单选按钮
<div>Picked: {{ picked }}</div>

<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>

<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>
5. 动态渲染
const selected = ref('A')

const options = ref([
  { text: 'One', value: 'A' },
  { text: 'Two', value: 'B' },
  { text: 'Three', value: 'C' }
])
<select v-model="selected">
  <option v-for="option in options" :value="option.value">
    {{ option.text }}
  </option>
</select>

<div>Selected: {{ selected }}</div>
6. 值绑定
<input type="radio" v-model="pick" :value="first" />
<input type="radio" v-model="pick" :value="second" />


监听器

  1. 用来Vue会监听数据的变化,并调用对应的回调函数
  2. 监听的数据包括:响应式的基础数据,响应式的对象,数组(数组元素是响应式的),或者getter方法
  3. 不能直接监听响应式对象的属性值
const x = ref(0)
const y = ref(0)

// 单个 ref
watch(x, (newX) => {
  console.log(`x is ${newX}`)
})

// getter 函数
watch(
  () => x.value + y.value,
  (sum) => {
    console.log(`sum of x + y is: ${sum}`)
  }
)

// 多个来源组成的数组
watch([x, () => y.value], ([newX, newY]) => {
  console.log(`x is ${newX} and y is ${newY}`)
})

const obj = reactive({ count: 0 })

// 错误,因为 watch() 得到的参数是一个 number
watch(obj.count, (count) => {
  console.log(`count is: ${count}`)
})
// 提供一个 getter 函数
watch(
  () => obj.count,
  (count) => {
    console.log(`count is: ${count}`)
  }
)


  1. 深层侦听器,被监听的对象的属性改变时,会触发函数的调用
  • 监听响应对象,默认是深层侦听
  • 一个返回响应式对象的 getter 函数,不是默认深层侦听,可以强制设置
watch(
 () => state.someObject,
 (newValue, oldValue) => {
   // 注意:`newValue` 此处和 `oldValue` 是相等的
   // *除非* state.someObject 被整个替换了
 },
 { deep: true }
)

一个返回响应式对象的 getter 函数
watch(
 () => state.someObject,
 (newValue, oldValue) => {
   //如果不强制深层的话,仅当 state.someObject 被替换时触发
   // 注意:`newValue` 此处和 `oldValue` 是相等的
   // *除非* state.someObject 被整个替换了
 },
 { deep: true }   // 强制深层监听
)

  1. 即时回调,watch是懒执行,只有被监听的数据变化的时候,才会执行对应的回调方法,如果希望初始的时候就执行对应的回调的方法,immediate: true
watch(source, (newValue, oldValue) => {
 // 立即执行,且当 `source` 改变时再次执行
}, { immediate: true })

6. watchEffect()

  • 不需要手动传入依赖
  • 每次初始化时会执行一次回调函数来自动获取依赖
  • 无法获取到原值,只能得到变化后的值
  1. 回调的触发时机:当响应的数据变化时,对应的vue组件会更新,对应的时机是先产生回调,组件之后再更新
// 强制将更新的时机调整到,Vue更新Dom之后
watch(source, callback, {
  flush: 'post'
})

watchEffect(callback, {
  flush: 'post'
})
  1. 停止侦听
  • 同步创建的侦听器会挂载到宿主组件上,我们不用关系如何停止
  • 异步创建的侦听器需要手动停止
  • watch和watchEffec监听器返回一个停止侦听的函数
const unwatch = watchEffect(() => {})

// ...当该侦听器不再需要时,这里的函数是对应侦听器的返回值
unwatch()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值