跳转至

Vue快速上手

声明式渲染

🔗 链接:

reactive()

📒 笔记:

  • 用于创建 JavaScript Proxy
  • 只适用于对象 (包括数组和内置类型,如 MapSet)
JavaScript
1
2
3
4
5
6
7
8
import { reactive } from 'vue'

const counter = reactive({
  count: 0
})

console.log(counter.count) // 0
counter.count++

ref()

📒 笔记:

  • 接受任何类型
  • 返回一个包裹对象,并在 .value 属性下暴露内部值
JavaScript
1
2
3
4
5
6
import { ref } from 'vue'

const message = ref('Hello World!')

console.log(message.value) // "Hello World!"
message.value = 'Changed'
完整代码
JavaScript
<script setup>
import { reactive, ref } from 'vue'

const counter = reactive({ count: 0 })
const message = ref('Hello World!')
</script>

<template>
  <h1>{{ message }}</h1>
  <p>Count is: {{ counter.count }}</p>
</template>

Attribute 绑定 v-bind

🔗 链接:

📒 笔记:

  • 在 Vue 中,mustache 语法 (即双大括号) 只能用于文本插值
  • attribute绑定动态值需要使用 v-bind 语法
JavaScript
<div v-bind:id="dynamicId"></div>
JavaScript
<div :id="dynamicId"></div>
完整代码
JavaScript
<script setup>
import { ref } from 'vue'

const titleClass = ref('title')
</script>

<template>
  <h1 :class="titleClass">Make me red</h1>
</template>

<style>
.title {
  color: red;
}
</style>

事件监听 v-on

🔗 链接:

JavaScript
<button v-on:click="handleClick">Click me</button>
JavaScript
<button @click="handleClick">Click me</button>
完整代码
JavaScript
<script setup>
import { ref } from 'vue'

const count = ref(0)

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

<template>
  <button @click="increment">count is: {{ count }}</button>
</template>

表单绑定 v-model

🔗 链接:

JavaScript
1
2
3
4
5
6
7
<input :value="text" @input="onInput">
...
function onInput(e) {
  // v-on 处理函数会接收原生 DOM 事件
  // 作为其参数。
  text.value = e.target.value
}
JavaScript
<input v-model="text">
完整代码
JavaScript
<script setup>
import { ref } from 'vue'

const text = ref('')

function onInput(e) {
  text.value = e.target.value
}
</script>

<template>
  <input :value="text" @input="onInput" placeholder="Type here">
  <p>{{ text }}</p>
</template>
JavaScript
<script setup>
import { ref } from 'vue'

const text = ref('')
</script>

<template>
  <input v-model="text" placeholder="Type here">
  <p>{{ text }}</p>
</template>

条件渲染 v-if

🔗 链接:

JavaScript
<h1 v-if="awesome">Vue is awesome!</h1>
JavaScript
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
完整代码
JavaScript
<script setup>
import { ref } from 'vue'

const awesome = ref(true)

function toggle() {
  awesome.value = !awesome.value
}
</script>

<template>
  <button @click="toggle">toggle</button>
  <h1 v-if="awesome">Vue is awesome!</h1>
  <h1 v-else>Oh no 😢</h1>
</template>

列表渲染 v-for

🔗 链接:

示例代码

JavaScript
1
2
3
4
5
<ul>
  <li v-for="todo in todos" :key="todo.id">
    {{ todo.text }}
  </li>
</ul>

更新列表有两种方式:

JavaScript
todos.value.push(newTodo)
JavaScript
todos.value = todos.value.filter(/* ... */)
完整代码
JavaScript
<script setup>
import { ref } from 'vue'

// 给每个 todo 对象一个唯一的 id
let id = 0

const newTodo = ref('')
const todos = ref([
  { id: id++, text: 'Learn HTML' },
  { id: id++, text: 'Learn JavaScript' },
  { id: id++, text: 'Learn Vue' }
])

function addTodo() {
  todos.value.push({ id: id++, text: newTodo.value })
  newTodo.value = ''
}

function removeTodo(todo) {
  todos.value = todos.value.filter((t) => t !== todo)
}
</script>

<template>
  <form @submit.prevent="addTodo">
    <input v-model="newTodo">
    <button>Add Todo</button>    
  </form>
  <ul>
    <li v-for="todo in todos" :key="todo.id">
      {{ todo.text }}
      <button @click="removeTodo(todo)">X</button>
    </li>
  </ul>
</template>

计算属性 computed()

🔗 链接:

📒 笔记:

  • 此API用于创建一个计算属性 ref,这个 ref 会动态地根据其他响应式数据源来计算其 .value

示例代码:

JavaScript
import { ref, computed } from 'vue'

const hideCompleted = ref(false)
const todos = ref([
  /* ... */
])

const filteredTodos = computed(() => {
  // 根据 `todos.value` & `hideCompleted.value`
  // 返回过滤后的 todo 项目
})
完整代码
JavaScript
<script setup>
import { ref, computed } from 'vue'

let id = 0

const newTodo = ref('')
const hideCompleted = ref(false)
const todos = ref([
  { id: id++, text: 'Learn HTML', done: true },
  { id: id++, text: 'Learn JavaScript', done: true },
  { id: id++, text: 'Learn Vue', done: false }
])

const filteredTodos = computed(() => {
  return hideCompleted.value
    ? todos.value.filter((t) => !t.done)
    : todos.value
})

function addTodo() {
  todos.value.push({ id: id++, text: newTodo.value, done: false })
  newTodo.value = ''
}

function removeTodo(todo) {
  todos.value = todos.value.filter((t) => t !== todo)
}
</script>

<template>
  <form @submit.prevent="addTodo">
    <input v-model="newTodo">
    <button>Add Todo</button>
  </form>
  <ul>
    <li v-for="todo in filteredTodos" :key="todo.id">
      <input type="checkbox" v-model="todo.done">
      <span :class="{ done: todo.done }">{{ todo.text }}</span>
      <button @click="removeTodo(todo)">X</button>
    </li>
  </ul>
  <button @click="hideCompleted = !hideCompleted">
    {{ hideCompleted ? 'Show all' : 'Hide completed' }}
  </button>
</template>

<style>
.done {
  text-decoration: line-through;
}
</style>

生命周期和模板引用 ref=

🔗 链接:

📒 笔记:

  • 使用模板引用: 指向模板中一个 DOM 元素的 ref,即<p ref="pElementRef">hello</p>
  • 访问引用: 声明一个同名的 ref,即const pElementRef = ref(null)
  • 要在挂载之后执行代码,需要使用 onMounted() 函数,即
JavaScript
1
2
3
4
5
import { onMounted } from 'vue'

onMounted(() => {
  // 此时组件已经挂载。
})
完整代码
JavaScript
<script setup>
import { ref, onMounted } from 'vue'

const pElementRef = ref(null)

onMounted(() => {
  pElementRef.value.textContent = 'mounted!'
})
</script>

<template>
  <p ref="pElementRef">hello</p>
</template>

侦听器 watch()

🔗 链接:

📒 笔记:

  • 侦听器的作用: 监听某个元素的变化,执行特定动作

示例代码

JavaScript
1
2
3
4
5
6
7
import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newCount) => {
  console.log(`new count is: ${newCount}`)
})
完整代码
JavaScript
<script setup>
import { ref, watch } from 'vue'

const todoId = ref(1)
const todoData = ref(null)

async function fetchData() {
  todoData.value = null
  const res = await fetch(
    `https://jsonplaceholder.typicode.com/todos/${todoId.value}`
  )
  todoData.value = await res.json()
}

fetchData()

watch(todoId, fetchData)
</script>

<template>
  <p>Todo id: {{ todoId }}</p>
  <button @click="todoId++">Fetch next todo</button>
  <p v-if="!todoData">Loading...</p>
  <pre v-else>{{ todoData }}</pre>
</template>

组件

🔗 链接:

📒 笔记:

  • 父组件可以在模板中渲染另一个组件作为子组件。
  • 要使用子组件,需要先导入它,即import ChildComp from './ChildComp.vue'
完整代码
JavaScript
1
2
3
4
5
6
7
<script setup>
import ChildComp from './ChildComp.vue'
</script>

<template>
  <ChildComp />
</template>
JavaScript
1
2
3
<template>
  <h2>A Child Component!</h2>
</template>

Props

🔗 链接:

📒 笔记:

  • 子组件可以通过 props 从父组件接受动态数据
完整代码
JavaScript
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const greeting = ref('Hello from parent')
</script>

<template>
  <ChildComp :msg="greeting" />
</template>
JavaScript
1
2
3
4
5
6
7
8
9
<script setup>
const props = defineProps({
  msg: String
})
</script>

<template>
  <h2>{{ msg || 'No props passed yet' }}</h2>
</template>

Emits

🔗 链接:

📒 笔记:

  • 子组件通过 emit 可以向父组件触发事件
完整代码
JavaScript
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const childMsg = ref('No child msg yet')
</script>

<template>
  <ChildComp @response="(msg) => childMsg = msg" />
  <p>{{ childMsg }}</p>
</template>
JavaScript
1
2
3
4
5
6
7
8
9
<script setup>
const emit = defineEmits(['response'])

emit('response', 'hello from child')
</script>

<template>
  <h2>Child component</h2>
</template>

插槽slots

🔗 链接:

📒 笔记:

  • 父组件可以通过插槽 slots 将模板片段传递给子组件
完整代码
JavaScript
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const msg = ref('from parent')
</script>

<template>
  <ChildComp>Message: {{ msg }}</ChildComp>
</template>
JavaScript
1
2
3
<template>
  <slot>Fallback content</slot>
</template>

参考