2024-03-31
全栈实战
0

目录

Vue
创建Vue项目
基于 Vite 创建
基于 CLI 创建
API
选项式 API (Options API)
组合式 API (Composition API)
响应式基础
ref 创建:基本类型的响应式数据
reactive 创建:对象类型的响应式数据
ref 创建:对象类型的响应式数据
ref 对比 reactive
toRefs 与 toRef
基础指令
v-text 与 v-html
v-model
v-model 的修饰符
.lazy 修饰符
.number 修饰符
.trim 修饰符
v-cloak
v-bind
v-on

一直想做一些自己的产品,记录下对前端知识的学习

Vue 是用于构建用户界面的 JavaScript 框架。

它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。

Vue

创建Vue项目

在创建 Vue 项目以前,我们需要先安装 Node.js

基于 Vite 创建

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

启动项目

shell
cd <your-project-name> npm install npm run dev

构建项目(当你准备将应用发布到生产环境时,运行)

shell
npm run build

基于 CLI 创建

备注:目前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

API

Vue 的组件可以按两种不同的风格书写:选项式 API组合式 API

选项式 API (Options 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 (Composition API)

通过组合式 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>

响应式基础

ref 创建:基本类型的响应式数据

  • **作用:**定义响应式变量。
  • 语法:let xxx = ref(初始值)
  • **返回值:**一个RefImpl的实例对象,简称ref对象refref对象的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>

reactive 创建:对象类型的响应式数据

  • 作用:定义一个响应式对象(基本类型不要用它,要用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接收的数据可以是:基本类型对象类型
  • 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

宏观角度看:

  1. ref用来定义:基本类型数据对象类型数据

  2. reactive用来定义:对象类型数据

  • 区别:
  1. ref创建的变量必须使用.value(可以使用volar插件自动添加.value)。 > > 自动补充value

  2. reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)。

  • 使用原则:
  1. 若需要一个基本类型的响应式数据,必须使用ref
  2. 若需要一个响应式对象,层级不深,refreactive都可以。
  3. 若需要一个响应式对象,且层级较深,推荐使用reactive

toRefs 与 toRef

  • 作用:将一个响应式对象中的每一个属性,转换为ref对象。
  • 备注:toRefstoRef功能一致,但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

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 指令用于实现双向数据绑定,它允许在表单元素(如输入框、选择框等)和数据之间进行双向绑定,从而实现数据的自动更新和显示。

v-model 的修饰符

.lazy 修饰符

在上面示例中默认情况下,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>
.number 修饰符

将用户输入的数据自动转换为数值类型

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) }}

.trim 修饰符

将用户输入的数据自动去除首尾空格

html
<template> <p>{{ msg }}</p> <input type="text" v-model.trim="msg"/> <br/> </template> <script setup> import { ref } from 'vue'; const msg = ref(''); </script>

v-cloak

模板语法有一个缺点: 可能会出现闪烁问题,即页面数据可能还没加载渲染完成,就提前出现了两对{}。

实际应用中可能就是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

v-bind 用来绑定标签上的属性( src、href、title 等等) 或样式(style、class )。

html
<img v-bind:src="imgUrl" alt="">

v-bind 可以简写成 :

html
<img :src="imgUrl" alt="">

修饰符

  • camel - 将短横线命名的 attribute 转变为驼峰式命名。
  • prop - 强制绑定为 DOM property (3.2+)。
  • attr - 强制绑定为 DOM attribute (3.2+)。

示例

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>

v-on

给元素绑定事件监听器。缩写:@

修饰符

  • stop - 调用 event.stopPropagation()。
  • prevent - 调用 event.preventDefault()。
  • capture - 在捕获模式添加事件监听器。
  • self - 只有事件从元素本身发出才触发处理函数。
  • {keyAlias} - 只在某些按键下触发处理函数。
  • once - 最多触发一次处理函数。
  • left - 只在鼠标左键事件触发处理函数。
  • right - 只在鼠标右键事件触发处理函数。
  • middle - 只在鼠标中键事件触发处理函数。
  • passive - 通过 { passive: true } 附加一个 DOM 事件。

本文作者:柳始恭

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!