Vue 学习笔记(一)
1、环境安装
# 创建项目
$ npm init vite vue-vite-ts
Need to install the following packages:
create-vite@3.2.0
Ok to proceed? (y) y
√ Select a framework: » Vue
√ Select a variant: » TypeScript
Scaffolding project in D:\vscode\vue-vite-ts...
Done. Now run:
cd vue-vite-ts
npm install
npm run dev
# 切换目录
$ cd vue-vite-ts
# 安装pnpm
$ npm install -g pnpm
# 安装依赖
$ pnpm i
# 运行
$ pnpm dev
2、如何修改启动端口号
- 修改package.json
"scripts": {
"dev": "vite --port 80",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
3、父组件给子组件传值
- 父组件:通过属性msg传值
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<HelloWorld msg="Vue + Vite" :id="23"/>
</template>
- 子组件:通过defineProps拿到父组件属性值
- 因为id是number,需要前面加上冒号
- string可以直接不用加冒号
<script setup lang="ts">
defineProps<{ msg: string,id:number }>()
</script>
<template>
<h1>{{ msg }}</h1>
</template>
4、模板语法
- 支持运算和方法调用
<script setup lang="ts">
import { ref } from 'vue';
defineProps<{ msg: string, id: number }>()
const name = ref('周末快乐')
// age=0为假反之为真
const age: number = 2
const temp = ref('周,末,快,乐')
</script>
<template>
<h1>msg:{{ msg }}</h1>
<h1>id:{{ id }}</h1>
<h2>{{name}},{{age}}</h2>
<!-- 使用表达式 -->
<h2>{{ age ? '我是真的' : '我是假的' }}</h2>
<h2>{{ temp.split(',') }}</h2>
<h2>{{ temp.split(',').map(i => ` 【${i}】 `) }}</h2>
</template>
5、指令
-
v- 开头都是vue 的指令
-
v-text 用来显示文本
-
v-html 用来展示富文本
-
v-if 用来控制元素的显示隐藏(切换真假DOM)
-
v-else-if 表示 v-if 的“else if 块”。可以链式调用
-
v-else v-if条件收尾语句
-
v-show 用来控制元素的显示隐藏(display none block Css切换)
-
v-on 简写@ 用来给元素添加事件
-
v-bind 简写: 用来绑定元素的属性Attr
-
v-model 双向绑定
<script>
import { ref } from 'vue';
// 必须用ref包括,否则无法双向绑定
const name = ref('周末快乐')
</script>
<template>
<input v-modle="name" type="text" />
<div>{{ name }}</div>
</template>
- v-for 用来遍历元素
<script>
const names = [{
id: 1,
name: "张三",
age: 18
}, {
id: 2,
name: "张三",
age: 18
}, {
id: 3,
name: "张三",
age: 18
}, {
id: 4,
name: "张三",
age: 18
}]
const arr = [1, 2, 3, 4, 5]
</script>
<div v-for="(item, i) in arr" :key="i">{{ i }}、{{ item }}</div>
<table border="1">
<tr v-for="item in names">
<td style="width: 60px;">{{ item.id }}</td>
<td style="width: 120px;">{{ item.name }}</td>
<td style="width: 80px;">{{ item.age }}</td>
</tr>
</table>
- v-on修饰符 冒泡案例
6、ref类型在事件中调用,需要使用value
let age = ref(0)
const changeNum = () => {
age.value++
}
7、阻止表单提交
<button @click.prevent="submit" type="submit">submit</button>
8、绑定样式和多类绑定
<script>
const styleTeml = {
"color": "green",
"height":"200px"
}
const flag = ref(false)
</script>
<template>
<h1 :style="styleTeml">绑定样式</h1>
<div :class="['a', 'b']">呵呵</div>
<button @click="flag = !flag">换颜色</button>
<div :class="[flag ? 'a' : 'c']">呵呵</div>
</template>
<style scoped>
.a {
color: aqua;
}
.b {
height: 200px;
}
.c {
color: red;
}
9、ref
- 接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value property,指向该内部值
- 在检查元素后面 点小齿轮,选中“启用自定义格式化工具”,可以直接查看ref
- customRef:customRef 是个工厂函数要求我们返回一个对象 并且实现 get 和 set 适合去做防抖之类的
- triggerRef:强制更新页面DOM
- ShallowRef:创建一个跟踪自身 .value 变化的 ref,但不会使其值也变成响应式的
- 注意被ref包装之后需要.value 来进行赋值
- 获取dom元素
<template>
<div ref="div" id="12">
我是div
</div>
<button @click="btn"> 获取dom</button>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const div = ref<HTMLElement>()
// 获取div内部内容
const btn = () => {
console.log(div.value?.innerHTML);
}
</script>
10、reactive
- 用来绑定复杂的数据类型 例如 对象 数组,Map,Set,但ref支持所有类型
- ref赋值需要加value,reactive不用
// 内部定义 ref
export declare function ref<T extends object>(value: T): [T] extends [Ref] ? T : Ref<UnwrapRef<T>>;
// 内部定义 reactive
export declare function reactive<T extends object>(target: T): UnwrapNestedRefs<T>;
- 表单提交
<template>
<form>
<input v-model="form.name" style="width: 200px;height: 30px;line-height: 20px;" type="text" />
<hr>
<input v-model="form.tel" style="width: 200px;height: 30px;line-height: 20px;" type="text" />
<hr>
<!-- 阻止默认的刷新 -->
<input type="submit" @click.prevent="btn" />
</form>
</template>
<script setup lang="ts">
import { ref, customRef, triggerRef, ShallowRef, reactive } from 'vue'
const div = ref<HTMLElement>()
const name = ref(6)
const form = reactive({
name: "",
tel: ""
})
const btn = () => {
console.log(form);
}
</script>
- 异步操作,无法更新ui
<template>
<button @click="btn">添加</button>
<li v-for="item in list"> {{ item }}</li>
</template>
<script setup lang="ts">
import { ref, customRef, triggerRef, ShallowRef, reactive } from 'vue'
let list: string[] = reactive([])
const btn = () => {
// 同步添加没有问题;
// list.push('add');
// 异步添加,直接赋值,则无法渲染,因为reactive是proxy对象,直接赋值会破坏响应式对象,两种解决办法,第一种 push+解构
setTimeout(() => {
// list = ['add', 'del', 'save']
// console.log(list);
// 第一种办法:
let res = ['add', 'del', 'save']
list.push(...res)
console.log(list);
}, 2000)
}
</script>
- 第二种解决异步问题,添加一个对象,把数组当做属性使用
<template>
<button @click="btn">添加</button>
<li v-for="item in list.arr"> {{ item }}</li>
</template>
<script setup lang="ts">
import { ref, customRef, triggerRef, ShallowRef, reactive } from 'vue'
let list = reactive<{ arr: string[] }>({
arr: []
})
const btn = () => {
// 同步添加没有问题;
// list.push('add');
// 异步添加,直接赋值,则无法渲染
setTimeout(() => {
let res = ['add', 'del', 'save']
list.arr = res
console.log(list);
}, 2000)
}
- readonly:把一个reactive赋值给readonly,就会变成只读,但是会受原始对象影响
<script setup lang="ts">
import { readonly, reactive } from 'vue'
let list = reactive({
name: "李四"
})
let listR = readonly(list)
const btn = () => {
console.log(list, listR)
}
</script>
世界上没有什么事情是跑步解决不了的,如果有,那就再跑一会!