一直想做一些自己的产品,记录下对前端知识的学习
Vue 是用于构建用户界面的 JavaScript 框架。
它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。
在创建 Vue 项目以前,我们需要先安装 Node.js。
Vue 官网推荐使用 Vite 创建项目
shell## 1.创建命令
npm create vue@latest
## 2.具体配置
## 配置项目名称
√ Project name: vue3_test
## 是否添加TypeScript支持
√ Add TypeScript? Yes
## 是否添加JSX支持
√ Add JSX Support? No
## 是否添加路由环境
√ Add Vue Router for Single Page Application development? No
## 是否添加pinia环境
√ Add Pinia for state management? No
## 是否添加单元测试
√ Add Vitest for Unit Testing? No
## 是否添加端到端测试方案
√ Add an End-to-End Testing Solution? » No
## 是否添加ESLint语法检查
√ Add ESLint for code quality? Yes
## 是否添加Prettiert代码格式化
√ Add Prettier for code formatting? No
启动项目
shellcd <your-project-name> npm install npm run dev
构建项目(当你准备将应用发布到生产环境时,运行)
shellnpm run build
备注:目前
vue-cli
已处于维护模式,官方推荐基于Vite
创建项目。
shell## 查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
## 安装或者升级你的@vue/cli
npm install -g @vue/cli
## 执行创建命令
vue create vue_test
## 随后选择3.x
## Choose a version of Vue.js that you want to start the project with (Use arrow keys)
## > 3.x
## 2.x
## 启动
cd vue_test
npm run serve
Vue 的组件可以按两种不同的风格书写:选项式 API 和 组合式 API。
使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 data、methods 和 mounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。
html<script>
export default {
// data() 返回的属性将会成为响应式的状态
// 并且暴露在 `this` 上
data() {
return {
count: 0
}
},
// methods 是一些用来更改状态与触发更新的函数
// 它们可以在模板中作为事件处理器绑定
methods: {
increment() {
this.count++
}
},
// 生命周期钩子会在组件生命周期的各个不同阶段被调用
// 例如这个函数就会在组件挂载完成后被调用
mounted() {
console.log(`The initial count is ${this.count}.`)
}
}
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与
下面是使用了组合式 API 与
html<script setup>
import { ref, onMounted } from 'vue'
// 响应式状态
const count = ref(0)
// 用来修改状态、触发更新的函数
function increment() {
count.value++
}
// 生命周期钩子
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>
let xxx = ref(初始值)
。RefImpl
的实例对象,简称ref对象
或ref
,ref
对象的value
属性是响应式的。JS
中操作数据需要:xxx.value
,但模板中不需要.value
,直接使用即可。let name = ref('张三')
来说,name
不是响应式的,name.value
是响应式的。html<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">年龄+1</button>
<button @click="showTel">点我查看联系方式</button>
</div>
</template>
<script setup lang="ts" name="Person">
import {ref} from 'vue'
// name和age是一个RefImpl的实例对象,简称ref对象,它们的value属性是响应式的。
let name = ref('张三')
let age = ref(18)
// tel就是一个普通的字符串,不是响应式的
let tel = '13888888888'
function changeName(){
// JS中操作ref对象时候需要.value
name.value = '李四'
console.log(name.value)
// 注意:name不是响应式的,name.value是响应式的,所以如下代码并不会引起页面的更新。
// name = ref('zhang-san')
}
function changeAge(){
// JS中操作ref对象时候需要.value
age.value += 1
console.log(age.value)
}
function showTel(){
alert(tel)
}
</script>
ref
,否则报错)let 响应式对象= reactive(源对象)
。Proxy
的实例对象,简称:响应式对象。reactive
定义的响应式数据是“深层次”的。html<template>
<div class="person">
<h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
<h2>游戏列表:</h2>
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
<h2>测试:{{obj.a.b.c.d}}</h2>
<button @click="changeCarPrice">修改汽车价格</button>
<button @click="changeFirstGame">修改第一游戏</button>
<button @click="test">测试</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { reactive } from 'vue'
// 数据
let car = reactive({ brand: '奔驰', price: 100 })
let games = reactive([
{ id: 'ahsgdyfa01', name: '英雄联盟' },
{ id: 'ahsgdyfa02', name: '王者荣耀' },
{ id: 'ahsgdyfa03', name: '原神' }
])
let obj = reactive({
a:{
b:{
c:{
d:666
}
}
}
})
function changeCarPrice() {
car.price += 10
}
function changeFirstGame() {
games[0].name = '流星蝴蝶剑'
}
function test(){
obj.a.b.c.d = 999
}
</script>
ref
接收的数据可以是:基本类型、对象类型。ref
接收的是对象类型,内部其实也是调用了reactive
函数。html<template>
<div class="person">
<h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2>
<h2>游戏列表:</h2>
<ul>
<li v-for="g in games" :key="g.id">{{ g.name }}</li>
</ul>
<h2>测试:{{obj.a.b.c.d}}</h2>
<button @click="changeCarPrice">修改汽车价格</button>
<button @click="changeFirstGame">修改第一游戏</button>
<button @click="test">测试</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { ref } from 'vue'
// 数据
let car = ref({ brand: '奔驰', price: 100 })
let games = ref([
{ id: 'ahsgdyfa01', name: '英雄联盟' },
{ id: 'ahsgdyfa02', name: '王者荣耀' },
{ id: 'ahsgdyfa03', name: '原神' }
])
let obj = ref({
a:{
b:{
c:{
d:666
}
}
}
})
console.log(car)
function changeCarPrice() {
car.value.price += 10
}
function changeFirstGame() {
games.value[0].name = '流星蝴蝶剑'
}
function test(){
obj.value.a.b.c.d = 999
}
</script>
宏观角度看:
ref
用来定义:基本类型数据、对象类型数据;
reactive
用来定义:对象类型数据。
ref
创建的变量必须使用.value
(可以使用volar
插件自动添加.value
)。 > >
reactive
重新分配一个新对象,会失去响应式(可以使用Object.assign
去整体替换)。
- 若需要一个基本类型的响应式数据,必须使用
ref
。- 若需要一个响应式对象,层级不深,
ref
、reactive
都可以。- 若需要一个响应式对象,且层级较深,推荐使用
reactive
。
ref
对象。toRefs
与toRef
功能一致,但toRefs
可以批量转换。html<template>
<div class="person">
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<h2>性别:{{person.gender}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="changeGender">修改性别</button>
</div>
</template>
<script lang="ts" setup name="Person">
import {ref,reactive,toRefs,toRef} from 'vue'
// 数据
let person = reactive({name:'张三', age:18, gender:'男'})
// 通过toRefs将person对象中的n个属性批量取出,且依然保持响应式的能力
let {name,gender} = toRefs(person)
// 通过toRef将person对象中的gender属性取出,且依然保持响应式的能力
let age = toRef(person,'age')
// 方法
function changeName(){
name.value += '~'
}
function changeAge(){
age.value += 1
}
function changeGender(){
gender.value = '女'
}
</script>
在Vue中,指令都是以v-
开头的,每个指令都是 JavaScript 表达式
v-text
用于设置元素的文本内容,v-html
指令用于设置元素的HTML内容
html<template>
<p>{{ msg }}</p>
<p v-text="msg"></p>
<p v-html="msg"></p>
</template>
<script setup>
import { ref } from 'vue';
const msg = ref('<a href="http://www.baidu.com"> Welcome </a>');
</script>
v-text, v-html、{{ }} 的正确使用与区别
v-text 与 v-html 指令都可以更新页面元素的内容,不同的是,v-text 会将数据以字符串文本的形式更新,而 v-html 则会直接将数据作为 HTML 标签内容更新。
在更新数据时,{{ }} 表达式只会更新原本占位插值所在的数据内容,而 v-text 与 v-html 指令则更新整个标签内容。
v-model
指令用于实现双向数据绑定,它允许在表单元素(如输入框、选择框等)和数据之间进行双向绑定,从而实现数据的自动更新和显示。
在上面示例中默认情况下,v-model 指令在每次 input 事件触发后会将输入框的值与响应式的msg进行同步,添加 .lazy
以后,则转变为失去焦点同步。
html<template>
{{ msg }}
<div>
双向绑定:<input v-model="msg" type="text"/>
</div>
<div>
失去焦点后双向绑定:<input v-model.lazy="msg" type="text"/>
</div>
</template>
<script setup>
import { ref } from 'vue';
const msg = ref('');
</script>
将用户输入的数据自动转换为数值类型
html<template>
<input v-model="num1" type="text"/>
<br/>
<input v-model="num2" type="text"/>
<br/>
{{ num1 + num2 }}
<br/>
<input v-model.number="num3" type="text"/>
<br/>
<input v-model.number="num4" type="text"/>
<br/>
{{ num3 + num4 }}
</template>
<script setup>
import { ref } from 'vue';
const num1 = ref('');
const num2 = ref('');
const num3 = ref('');
const num4 = ref('');
</script>
以上示例中 .number
修饰符绑定的值会想加,而不是字符串拼接,如果不想要修饰符,可以使用以下方式
vue{{ parseInt(num1) + parseInt(num2) }}
将用户输入的数据自动去除首尾空格
html<template>
<p>{{ msg }}</p>
<input type="text" v-model.trim="msg"/> <br/>
</template>
<script setup>
import { ref } from 'vue';
const msg = ref('');
</script>
模板语法有一个缺点: 可能会出现闪烁问题,即页面数据可能还没加载渲染完成,就提前出现了两对{}。
实际应用中可能就是Vue实例中的数据。例如,通过发送异步请求获取来自网络(服务器)的数据,由于网络或者数据量大,需要一定的时间,这个时候Vue中的数据(Data)尚没有数据,就不会去渲染视图,那么在视图中会提前看到类似{{msg}的情况,这给用户的体验很不好,所以在数据尚未加载渲染完成时不要让类似{{msg}}出现,那么如何解决呢?可以使用v-cloak 指令来解决。
使用 v-cloak 指令要配合CSS样式一起使用否则不会生效。 通过CSS样式先设置为不显示,在数据流染完成之后就会自动修改displs值为显示。
html<template>
<div v-cloak>
{{ message }}
</div>
</template>
<script setup>
import { ref,onMounted } from 'vue';
const message = ref('123');
onMounted(()=>{
alert('挂载完毕')
})
</script>
<style>
[v-cloak] {
display: none;
}
</style>
v-bind 用来绑定标签上的属性( src、href、title 等等) 或样式(style、class )。
html<img v-bind:src="imgUrl" alt="">
v-bind 可以简写成 :
html<img :src="imgUrl" alt="">
修饰符
示例
html<!-- 绑定 attribute -->
<img v-bind:src="imageSrc" />
<!-- 动态 attribute 名 -->
<button v-bind:[key]="value"></button>
<!-- 缩写 -->
<img :src="imageSrc" />
<!-- 缩写形式的动态 attribute 名 (3.4+),扩展为 :src="src" -->
<img :src />
<!-- 动态 attribute 名的缩写 -->
<button :[key]="value"></button>
<!-- 内联字符串拼接 -->
<img :src="'/path/to/images/' + fileName" />
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]"></div>
<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 绑定对象形式的 attribute -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!-- prop 绑定。“prop” 必须在子组件中已声明。 -->
<MyComponent :prop="someThing" />
<!-- 传递子父组件共有的 prop -->
<MyComponent v-bind="$props" />
<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>
给元素绑定事件监听器。缩写:@
修饰符
本文作者:柳始恭
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!