本页内容基于VUE3.2版本,且以组合式API模式编写<script setup>

推荐的 IDE 配置是 Visual Studio Code + Volar 扩展

中文文档:https://staging-cn.vuejs.org/

使用Vite安装Vue

npm init vite@latest <project-name> -- --template vue
# 或者
npm create vite@latest <project-name> -- --template vue

cd <project-name>
npm install
npm run dev

模板语法

// 显示文本
<span>Message: {{ msg }}</span>

// 显示原始HTML
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

// 绑定HTML属性
<div v-bind:id="dynamicId"></div>
// 绑定多个HTML属性
<div v-bind="objectOfAttrs"></div>

// 调用函数
<span :title="toTitleDate(date)">
  {{ formatDate(date) }}
</span>

// 绑定动态参数
<a v-bind:[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>
// 如果需要操作['foo' + bar],建议使用计算属性

// 修饰符
<form @submit.prevent="onSubmit">...</form>
//  绑定多个HTML属性
const objectOfAttrs = {
  id: 'container',
  class: 'wrapper'
}

简写:

v-bind简写为:

v-on简写为@

响应式

<script setup>
import { ref,reactive } from 'vue';
const count = ref(0);
console.log(count.value) // 0
// ref声明的对象,在程序内使用需要加.value
const count1 = $ref(0);
console.log(count1) // 0
// 使用$ref声明响应式对象,使用时无需.value

const state = reactive({
    num:0
});
console.log(state.num) // 0
function increment() {
  state.num++
}
</script>
<template>
  <button @click="increment">
    {{ state.num }}
  </button>
  <p>{{count}}</p>
</template>

计算属性

与方法的区别:计算属性值会基于响应式依赖关系被缓存,只在响应式依赖更新时才会重新计算,重新渲染时不会被更新

计算属性格式:

import { ref,reactive,computed } from 'vue'
const state = reactive({
    num:0
});

//计算属性
const count = computed(()=>{
  return state.num > 0 ? 'Yes' : 'No';
});
// 模板中使用:{{ count }}

//对应方法
function count(){
  return state.num > 0 ? 'Yes' : 'No';
}
// 模板中使用:{{ count() }}

计算属性被是为“临时快照”,返回的值是派生状态,默认使用get方法,也可以使用set方法来更新更新派生值,不要在计算属性中通过异步请求修改原始值

条件渲染

<p v-if=""></p>
<p v-else-if=""></p>
<p v-else></p>

<p v-show></p>
// v-show只修改元素的display依然会保留元素但v-if不会保留

列表渲染

v-for是用来将数据渲染到列表

<li v-for="item in items">
  {{ item.message }}
</li>

<li v-for="(item, index) in items">
  //item 单项别名
  // index 单项索引
</li>

对应JavaScript代码

const items = [];
items.forEach((item.index)=>{
  //...
});

循环整数

<span v-for="n in 10">{{ n }}</span>

v-for也可以遍历对象

<ul>
  <li v-for="value in myObject">
    {{ value }}
  </li>
</ul>

<li v-for="(value, key) in myObject">
  {{ key }}: {{ value }}
</li>

<li v-for="(value, key, index) in myObject">
  {{ index }}. {{ key }}: {{ value }}
</li>

template上使用v-for

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

通过key管理状态

如果是简单的列表,vue会自动将index作为key,如果复杂的列表需要单独设置一个唯一key,唯一key可以保证每次更新只更新单个元素而非整个列表

<div v-for="item in items" :key="item.id">
  <!-- 内容 -->
</div>

组件上使用v-for

<my-component
  v-for="(item, index) in items"
  :item="item"
  :index="index"
  :key="item.id"
></my-component>

必须将item以prop形式传给子组件,子组件才可以使用

过滤或排序

使用计算属性预先处理原始数据即可 JavaScript常见变更数组方法:push()、pop()、shift()、unshift()、splice()、sort()、reverse() 不变更数据方法:filter(),concat() 和 slice()

事件处理

事件监听: v-on:click="methodName"@click="handler"

内联事件

const count = ref(0)
<button @click="count++">Add 1</button>

方式事件

function say(message) {
  alert(message)
}
<button @click="say('hello')">Say hello</button

事件修饰符

  • .stop
  • .prevent
  • .self
  • .capture
  • .once
  • .passive
<!-- 单击事件将停止传递 -->
<a @click.stop="doThis"></a>

按键修饰符

  • .enter
  • .tab
  • .delete (捕获“Delete”和“Backspace”两个按键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
<!-- 仅在 `key` 为 `Enter` 时调用 `vm.submit()` -->
<input @keyup.enter="submit" />

系统按键修饰符

  • .ctrl
  • .alt
  • .shift
  • .meta
<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" />

<!-- Ctrl + 点击 -->
<div @click.ctrl="doSomething">Do something</div>

鼠标按键修饰符

  • .left
  • .right
  • .middle

表单输入绑定

基本用法

// 文本
<input v-model="message" />

// 多行文本
<textarea v-model="message"></textarea>

// 复选框 const checked = ref(true)
<input type="checkbox" id="checkbox" v-model="checked" />
// 如果将checked设置为数组,且多个input绑定了checked,则选中的结果或存放在checked数组中,const checkedNames = ref([])

// 单选框 const picked = ref('One')
<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>

// 下拉框单选 const selected = ref('')
<select v-model="selected">
  <option disabled value="">Please select one</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

// 下拉多选 const selected = ref([])
<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

Vue组件

使用组件

// 子组件 Bar.vue
<script setup>
<template>
  <h1>这是子组件</h1>
</template>

// 父组件 Foo.vue
<script setup>
import Bar from './Bar.vue' //引入子组件
</script>

<template>
  <h1>这是父组件</h1>
  <Bar /> // 使用子组件
</template>

传递props

用于父组件给子组件传递值

<!-- 子组件BlogPost.vue -->
<script setup>
defineProps(['title']) //生命参数
// const props = defineProps(['title'])
// console.log(props.title)
// 限制格式
// defineProps({
//  title: String,
//  likes: Number
//}})
</script>

<template>
  <h4>{{ title }}</h4> <!-- 使用参数 -->
</template>

<!-- 父组件Blog.vue将值传给参数title -->
<BlogPost title="My journey with Vue" />

监听事件

父组件监听子组件事件(将子组件事件传给父组件)

方法1:使用$emit方法监听事件

使用$emit声明一个事件,然后在父组件中监听这个事件,当事件触发后父组件执行相应的其它事件

// 父组件
<BlogPost
  ...
  @do="doSomething"
 />

// 子组件
<button @click="$emit('do')">Do Something</button>

//<button @click="$emit('do','传给父组件的内容','...')">Do Something</button>

方法2:使用defineEmits监听子组件事件,并获取回传的参数值

// 父组件
function doSomething(data){
  alert(data) //data:回传的值
}

<BlogPost
  ...
  @do="doSomething"
 />

// 子组件
const emit = defineEmits(['do'])
const do = ()=>{
  emit('do','回传的值')
}

<button @click="do">Do Something</button>

方法3:组件上使用v-model来实现子父组件之间内容传递

插槽

插槽<slot>是占位符,用来在子组件中对应位置显示父组件传递的内容(也可以通过传值的方式来替代插槽)

// 父组件
<Bar>
这是父组件传递的内容
</Bar>

// 子组件
<p>这是子组件的一部分内容</p>
<slot /> <!--这儿会显示父组件传递的内容-->
<p>这是子组件的另一部分内容</p>