当前位置: 首页 > news >正文

vue3、vite、pinia 快速入门

准备 开发工具及插件

IDE:vscode,WebStorm

插件:Auto Close Tag、Auto Rename Tag、Live Server

通过“!”快速生成html模板

正式学习

安装vue

通过CDN的方式导入vue

<script src="" target="_blank">https://unpkg.com/vue@3/dist/vue.global.js"></script>

模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层组件实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。

在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应性系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX 语法。

插值


文本 {{}}

数据绑定最常见的形式就是使用“Mustache” (双大括号) 语法的文本插值:

<span>Message: {{ msg }}</span>

Mustache 标签将会被替代为对应组件实例中 msg property 的值。无论何时,绑定的组件实例上 msg property 发生了改变,插值处的内容都会更新。

通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:

<spanv-once>这个将不会改变: {{ msg }}</span>

原始 HTML及v-html

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用v-html 指令

<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <spanv-html="rawHtml"></span></p>

Attribute(属性) v-bind

Mustache 语法不能在 HTML attribute 中使用,然而,可以使用 v-bind 指令

<div v-bind:id="dynamicId"></div>
<div :id="dynamicId"></div>(缩写) 

如果绑定的值是 null 或 undefined,那么该 attribute 将不会被包含在渲染的元素上。

对于布尔 attribute (它们只要存在就意味着值为 true),v-bind 工作起来略有不同,在这个例子中:

<button v-bind:disabled="isButtonDisabled">按钮</button>

如果 isButtonDisabled 的值是 truthy[1],那么 disabled attribute 将被包含在内。如果该值是一个空字符串,它也会被包括在内,与 <button disabled=""> 保持一致。对于其他 falsy[2] 的值,该 attribute 将被省略。

使用 JavaScript 表达式

迄今为止,在我们的模板中,我们一直都只绑定简单的 property 键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。

{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>

这些表达式会在当前活动实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。

<!--  这是语句,不是表达式:-->
{{ var a = 1 }}
<!-- 流程控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}

动态参数(属性值可以变换)

也可以在指令参数中使用 JavaScript 表达式,方法是用方括号括起来:

<!--
注意,参数表达式的写法存在一些约束,如之后的“对动态参数表达式的约束”章节所述。
-->
<a v-bind:[attributename]="url"> ... </a>
属性值 attributename 不能有大写

这里的 attributeName 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的组件实例有一个 data property attributeName,其值为 "href",那么这个绑定将等价于 v-bind:href。

同样地,你可以使用动态参数为一个动态的事件名绑定处理函数:

<a v-on:[eventName]="doSomething"> ... </a>

在这个示例中,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus

缩写


v- 前缀作为一种视觉提示,用来识别模板中 Vue 特定的 attribute。当你在使用 Vue.js 为现有标签添加动态行为 (dynamic behavior) 时,v- 前缀很有帮助,然而,对于一些频繁用到的指令来说,就会感到使用繁琐。同时,在构建由 Vue 管理所有模板的单页面应用程序 (SPA - single page application) 时,v- 前缀也变得没那么重要了。因此,Vue 为 v-bind 和 v-on 这两个最常用的指令,提供了特定简写:

v-bind 缩写

<!-- 完整语法 -->
<av-bind:href="url"> ... </a>
<!-- 缩写 -->
<a:href="url"> ... </a>
<!-- 动态参数的缩写 -->
<a:[key]="url"> ... </a>

v-on 缩写

<!-- 完整语法 -->
<a v-on:click="doSomething"> ... </a>
<!-- 缩写 -->
<a @click="doSomething"> ... </a>
<!-- 动态参数的缩写 -->
<a @[event]="doSomething"> ... </a>

它们看起来可能与普通的 HTML 略有不同,但 : 与 @ 对于 attribute 名来说都是合法字符,在所有支持 Vue 的浏览器都能被正确地解析。而且,它们不会出现在最终渲染的标记中。缩写语法是完全可选的,但随着你更深入地了解它们的作用,你会庆幸拥有它们。

条件渲染

v-if


v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。

<h1 v-if="awesome">Vue is awesome!</h1>

也可以用 v-else 添加一个“else 块”:

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>

在 <template> 元素上使用 v-if 条件渲染分组

因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 <template> 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 <template> 元素。

1

<template v-if="ok">
<h1>Title</h1><p>Paragraph 1</p><p>Paragraph 2</p>
</template>

v-else

你可以使用 v-else 指令来表示 v-if 的“else 块”:

<div v-if="Math.random() > 0.5">Now you see me
</div>
<div v-else>Now you don't
</div>

v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。

v-else-if

v-else-if,顾名思义,充当 v-if 的“else-if 块”,并且可以连续使用:

<div v-if="type === 'A'">A
</div>
<div v-else-if="type === 'B'">B
</div>
<div v-else-if="type === 'C'">C
</div>
<div v-else>Not A/B/C
</div>

与 v-else 的用法类似,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

v-show


另一个用于条件性展示元素的选项是 v-show 指令。用法大致一样:

<h1 v-show="ok">Hello!</h1>

1

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 display CSS property。

注意,v-show 不支持 <template> 元素,也不支持 v-else。

v-if vs v-show


v-if 是“真正”的条件渲染,因为它会确保在切换过程中,条件块内的事件监听器和子组件适当地被销毁和重建。

v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

列表渲染

在 v-for 里使用值的范围


v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

<div id="range" class="demo"><span v-for="n in 10" :key="n">{{ n }} </span>
</div>

用 v-for 把一个数组映射为一组元素


我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名

<ul id="array-rendering"><li v-for="item in items">{{ item.message }}</li>
</ul>
Vue.createApp({data() {return {items: [{ message: 'Foo' }, { message: 'Bar' }]}}
}).mount('#array-rendering')

在 v-for 块中,我们可以访问所有父作用域的 property。v-for 还支持一个可选的第二个参数,即当前项的索引。

<ul id="array-with-index"><li v-for="(item, index) in items">{{ parentMessage }} - {{ index }} - {{ item.message }}</li>
</ul>

Vue.createApp({data() {return {parentMessage: 'Parent',items: [{ message: 'Foo' }, { message: 'Bar' }]}}
}).mount('#array-with-index')

你也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:

<div v-for="item of items"></div>

在 v-for 里使用对象


你也可以用 v-for 来遍历一个对象的 property。

<ul id="v-for-object" class="demo"><li v-for="value in myObject">{{ value }}</li>
</ul>
Vue.createApp({data() {return {myObject: {title: 'How to do lists in Vue',author: 'Jane Doe',publishedAt: '2016-04-10'}}}
}).mount('#v-for-object')

你也可以提供第二个的参数为 property 名称 (也就是键名 key):

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

还可以用第三个参数作为索引:


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

维护状态


当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一的 key attribute:

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

建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。

提示

不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。

在 <template> 中使用 v-for


类似于 v-if,你也可以利用带有 v-for 的 <template> 来循环渲染一段包含多个元素的内容。比如:

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

v-for 与 v-if 一同使用


TIP

注意我们推荐在同一元素上使用 v-if 和 v-for。更多细节可查阅风格指南

当它们处于同一节点,v-if 的优先级比 v-for 更高,这意味着 v-if 将没有权限访问 v-for 里的变量:

<!-- 这将抛出一个错误,因为“todo” property 没有在实例上定义 --><li v-for="todo in todos" v-if="!todo.isComplete">{{ todo.name }}
</li>

可以把 v-for 移动到 <template> 标签中来修正:

<template v-for="todo in todos" :key="todo.name"><li v-if="!todo.isComplete">{{ todo.name }}</li>
</template>

事件处理

监听事件


我们可以使用 v-on 指令 (通常缩写为 @ 符号) 来监听 DOM 事件,并在触发事件时执行一些 JavaScript。用法为 v-on:click="methodName" 或使用快捷方式 @click="methodName"

例如:

<div id="app"><button @click="counter += 1">Add 1</button><p>The button above has been clicked {{ counter }} times.</p>
</div>
Vue.createApp({data() {return {counter: 0}}
}).mount('#app')

事件处理方法


然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。因此 v-on 还可以接收一个需要调用的方法名称。

例如:


<div id="app"><!-- `greet` 是在下面定义的方法名 --><button @click="greet">Greet</button>
</div>
Vue.createApp({data() {return {name: 'Vue.js'}},methods: {greet(event) {// `methods` 内部的 `this` 指向当前活动实例alert('Hello ' + this.name + '!')// `event` 是原生 DOM eventif (event) {alert(event.target.tagName)}}}
}).mount('#app')

内联处理器中的方法


除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:


<div id="app"><button @click="say('hi')">Say hi</button><button @click="say('what')">Say what</button>
</div>

Vue.createApp({methods: {say(message) {alert(message)}}
}).mount('#app')

有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:

<button @click="warn('Form cannot be submitted yet.', $event)">Submit
</button>
// ...
methods: {warn(message, event) {// 现在可以访问到原生事件if (event) {event.preventDefault()}alert(message)}
}

#多事件处理器


事件处理程序中可以有多个方法,这些方法由逗号运算符分隔:


<!-- 这两个 one() 和 two() 将执行按钮点击事件 -->
<button @click="one($event), two($event)">Submit
</button>
methods: {one(event) {// 第一个事件处理器逻辑...},two(event) {// 第二个事件处理器逻辑...}
}

按键修饰符


在监听键盘事件时,我们经常需要检查特定的按键。Vue 允许为 v-on 或者 @ 在监听键盘事件时添加按键修饰符:


<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input @keyup.enter="submit" />

你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。

<input @keyup.page-down="onPageDown" />

在上述示例中,处理函数只会在 $event.key 等于 'PageDown' 时被调用。

#按键别名

Vue 为最常用的键提供了别名:

  • .enter

  • .tab

  • .delete (捕获“删除”和“退格”键)

  • .esc

  • .space

  • .up

  • .down

  • .left

  • .right

#系统修饰键


可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

  • .ctrl

  • .alt

  • .shift

  • .meta

提示

注意:在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。在 Symbolics 键盘上,meta 被标记为“META”或者“Meta”。

例如:

<!-- Alt + Enter -->
<input @keyup.alt.enter="clear" /><!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>

请注意修饰键与常规按键不同,在和 keyup 事件一起用时,事件触发时修饰键必须处于按下状态。换句话说,只有在按住 ctrl 的情况下释放其它按键,才能触发 keyup.ctrl。而单单释放 ctrl 也不会触发事件。

#.exact 修饰符

.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button><!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button><!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>

#鼠标按钮修饰符

  • .left

  • .right

  • .middle

这些修饰符会限制处理函数仅响应特定的鼠标按钮

表单输入绑定

官方文档地址:https://v3.cn.vuejs.org/guide/forms.html

基础用法


你可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件来更新数据,并在某种极端场景下进行一些特殊处理。

v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值。它将始终将当前活动实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 元素使用 value property 和 input 事件;

  • checkbox 和 radio 使用 checked property 和 change 事件;

  • select 字段将 value 作为 prop 并将 change 作为事件。

对于需要使用输入法 (如中文、日文、韩文等) 的语言,你会发现 v-model 不会在输入法组织文字过程中得到更新。如果你也想响应这些更新,请使用 input 事件监听器和 value 绑定来替代 v-model。

文本 (Text)

<input v-model="message" placeholder="edit me" />
<p>Message is: {{ message }}</p>

多行文本 (Textarea)

<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br />
<textarea v-model="message" placeholder="add multiple lines"></textarea>

插值在 textarea 中不起作用,请使用 v-model 来代替。

<!-- bad -->
<textarea>{{ text }}</textarea><!-- good -->
<textarea v-model="text"></textarea>

#复选框 (Checkbox)

单个复选框,绑定到布尔值:


<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>

多个复选框,绑定到同一个数组:

<div id="v-model-multiple-checkboxes"><input type="checkbox" id="jack" value="Jack" v-model="checkedNames" /><label for="jack">Jack</label><input type="checkbox" id="john" value="John" v-model="checkedNames" /><label for="john">John</label><input type="checkbox" id="mike" value="Mike" v-model="checkedNames" /><label for="mike">Mike</label><br /><span>Checked names: {{ checkedNames }}</span>
</div>
Vue.createApp({data() {return {checkedNames: []}}
}).mount('#v-model-multiple-checkboxes')

Class 与 Style 绑定

操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute,所以我们可以用 v-bind 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind 用于 class 和 style 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。

对象语法

我们可以传给 :class (v-bind:class 的简写) 一个对象,以动态地切换 class:

<div :class="{ active: isActive }"></div>

上面的语法表示 active 这个 class 存在与否将取决于 data property isActive 的 truthiness

你可以在对象中传入更多字段来动态切换多个 class。此外,:class 指令也可以与普通的 class attribute 共存。当有如下模板:

<divclass="static":class="{ active: isActive, 'text-danger': hasError }"
></div>

和如下 data:

data() {return {isActive: true,hasError: false}
}

渲染的结果为:

<div class="static active"></div>

当 isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"。

绑定的数据对象不必内联定义在模板里:

<div :class="classObject"></div>
data() {return {classObject: {active: true,'text-danger': false}}
}

使用vite创建项目

1.安装NODEJS


登录网站nodejs官方网站:http://nodejs.cn/download/

下载 安装长期支持版本

2.使用vite创建项目


vite官方网站

https://vitejs.cn/guide/#scaffolding-your-first-vite-project

在命令行中执行命令:npm init vite@latest

选择创建 vue-js 项目

Install Volar in your IDE for a better DX

运行项目:

cd projectName
npm install
npm run dev

VUE生命周期

生命周期图示


下图展示了实例的生命周期。我们不需要立马弄明白所有的东西,不过随着不断学习和使用,它的参考价值会越来越高

https://cn.vuejs.org/assets/lifecycle.16e4c08e.png

示例代码:

<template><div>{{ testval }}<button @click="clickMe">点我</button></div>
</template><script>
export default {data() {return {testval: "testval",};},methods: {clickMe() {this.testval = "testval2";},},beforeCreate() {console.log("beforeCreate");},created() {console.log("created");},beforeMount() {console.log("beforeMount");},mounted() {console.log("mounted");},beforeUpdate() {console.log("beforeUpdate");},updated() {console.log("updated");},beforeUnmount() {console.log("beforeUnmount");},unmounted() {console.log("unmounted");},
};
</script><style></style>

watch的使用

watch:用于监听data里面的数据是否被修改

watch在监听的时候,可以有二次参数,第一次参数为更新的数据,第二个参数为之前的旧数据

data() {return {text: '旧数据',}
},
watch: {text: function (newData, oldData) {//newData是更新后的数据//oldData是旧数据console.log(newData, oldData)}
}

watch只会监听第一层,而对象的数据修改了,但对象它的首地址没有修改,所以watch判定它没有发生数据的变化,从而监听不到,所以我们要使用deep 开启深层监听

data(){return {text:{name:'张三',age:21},}
},
watch: {//当想要监听对象的时候,想要开启深度监听//deep:truetext: {//此时旧数据不记录,oldval和newval指向同一块地址,所有值一样handler:function (newval) {console.log(newval)},deep:true}
}

computed的使用

1.定义


computed是vue的计算属性,是根据依赖关系进行缓存的计算,只有在它的相关依赖发生改变时才会进行更新

<template><div>{{ "今天天气是:" + weather + ",时间是:" + new Date().toISOString() }}<br />{{ dayInfo }}</div>
</template><script>
export default {data() {return {weather: "晴天",};},computed: {dayInfo() {return ("今天天气是:" + this.weather + ",时间是:" + new Date().toISOString());},},
}
</script>

自定义组件(emit事件,props组件属性,slot,组件v-model)

组件是带有名称的可复用实例

装Vue vscode snippets用于代码提示

本例我们开发一个对话框组件作为实例:

在components文件夹里,创建一个MyDialog.vue文件

<template><div class="dialog-bg"><div class="dialog"><div>{{ message }}</div><div><input type="text" v-model="modelValue" @keydown.enter="submit" @keydown.esc="cancel" /></div><div class="btn-group"><button @click="submit">确定</button><button @click="cancel">取消</button></div></div></div>
</template><script>
export default {props: {modelValue: {type: String,default: "",},message: {type: String,default: "",},},data() {return {};},created() {console.log("created");},beforeUnmount() {console.log("beforeUnmount");},unmounted() {console.log("unmounted");},methods: {submit() {this.$emit("update:model-value", this.modelValue);this.$emit("submit",this.modelValue)},cancel(){this.$emit("cancel")}},
};
</script><style scoped>
.dialog-bg {position: fixed;top: 0;left: 0;width: 100vw;height: 100vh;text-align: center;
}
.dialog {width: 300px;padding: 20px;margin: 0 auto;margin-top: 200px;background-color: #e4e4e4;
}.btn-group {margin-top: 50px;display: flex;justify-content: space-around;
}
</style>

在App.vue中引入该组件并显示出来

<template>{{ testVal }}<button @click="testClick">显示对话框</button><my-dialogv-if="showDialog"title="测试标题"v-model="testVal"@submit="dialogSubmit"@cancel="dialogCancel"><template v-slot:top="slotParam" ><div style="color:red">我的标题-{{slotParam.title}}</div></template><!-- <template #top="slotParam" ><div style="color:red">我的标题-{{slotParam.title}}</div></template> --><div>请填写修改的内容</div></my-dialog>
</template><script >
import MyDialog from "./components/MyDialog.vue";export default {components: {MyDialog,},data() {return {testVal: "hello",showDialog: false,};},methods: {testClick() {this.showDialog = true;},dialogSubmit() {this.showDialog = false;},dialogCancel() {this.showDialog = false;},},
};
</script><style></style>

emit事件(子组件到父组件)

props组件属性(父到子)

slot插槽(父到子)

默认

命名,多个slot插槽

slot 子传信息到父

v-model组件数据双向绑定

父到子传递信息

双向传递信息(事件触发子到父传递信息)

组合式 API 基础


既然我们知道了为什么,我们就可以知道怎么做。为了开始使用组合式 API,我们首先需要一个可以实际使用它的地方。在 Vue 组件中,我们将此位置称为 setup

带 ref、reactive 的响应式变量

ref 接收参数并将其包裹在一个带有 value property 的对象中返回,然后可以使用该 property 访问或更改响应式变量的值:

import { ref,reactive } from 'vue'const counter = ref(0)
const user = reactive({name:"张三",age:13})console.log(counter) // { value: 0 }
console.log(counter.value) // 0counter.value++
console.log(counter.value) // 1

将值封装在一个对象中,看似没有必要,但为了保持 JavaScript 中不同数据类型的行为统一,这是必须的。这是因为在 JavaScript 中,Number 或 String 等基本类型是通过值而非引用传递的

在 setup 内注册生命周期钩子

为了使组合式 API 的功能和选项式 API 一样完整,我们还需要一种在 setup 中注册生命周期钩子的方法。这要归功于 Vue 导出的几个新函数。组合式 API 上的生命周期钩子与选项式 API 的名称相同,但前缀为 on:即 mounted 看起来会像 onMounted。

这些函数接受一个回调,当钩子被组件调用时,该回调将被执行。

让我们将其添加到 setup 函数中:

// src/components/UserRepositories.vue `setup` function
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted } from 'vue'// 在我们的组件中
setup (props) {const repositories = ref([])const getUserRepositories = async () => {repositories.value = await fetchUserRepositories(props.user)}onMounted(getUserRepositories) // 在 `mounted` 时调用 `getUserRepositories`return {repositories,getUserRepositories}
}

现在我们需要对 user prop 的变化做出反应。为此,我们将使用独立的 watch 函数。

#watch 响应式更改

就像我们在组件中使用 watch 选项并在 user property 上设置侦听器一样,我们也可以使用从 Vue 导入的 watch 函数执行相同的操作。它接受 3 个参数:

  • 一个想要侦听的响应式引用或 getter 函数

  • 一个回调

  • 可选的配置选项

下面让我们快速了解一下它是如何工作的

import { ref, watch } from 'vue'const counter = ref(0)
watch(counter, (newValue, oldValue) => {console.log('The new counter value is: ' + counter.value)
})

每当 counter 被修改时,例如 counter.value=5,侦听将触发并执行回调 (第二个参数),在本例中,它将把 'The new counter value is:5' 记录到控制台中。

以下是等效的选项式 API:

export default {data() {return {counter: 0}},watch: {counter(newValue, oldValue) {console.log('The new counter value is: ' + this.counter)}}
}

独立的 computed 属性

与 ref 和 watch 类似,也可以使用从 Vue 导入的 computed 函数在 Vue 组件外部创建计算属性。让我们回到 counter 的例子:

import { ref, computed } from 'vue'const counter = ref(0)
const twiceTheCounter = computed(() => counter.value * 2)counter.value++
console.log(counter.value) // 1
console.log(twiceTheCounter.value) // 2

这里我们给 computed 函数传递了第一个参数,它是一个类似 getter 的回调函数,输出的是一个只读响应式引用。为了访问新创建的计算变量的 value,我们需要像 ref 一样使用 .value property。

使用组合式API编写组件

使用组合式api重新编写MyDialog.vue

创建新文件MyDialogSetup.vue

<template><div class="dialog-bg"><div class="dialog"><slot name="top" :title="title">{{ title }}</slot><div><slot></slot></div><div><inputtype="text"v-model="modelValue"@keydown.enter="submit"@keydown.esc="cancel"/></div><div class="btn-group"><button @click="submit">确定</button><button @click="cancel">取消</button></div></div></div>
</template><script setup lang="ts">
import { ref, reactive, onBeforeUnmount, onUnmounted } from "vue"; //定义属性
let props = defineProps({modelValue: {type: String,default: "",},title: {type: String,default: "",},
});//事件触发器
let emit = defineEmits({});function submit() {emit("update:model-value", props.modelValue);emit("submit", props.modelValue);
}
function cancel() {emit("cancel");
}//生命周期
onBeforeUnmount(() => {console.log("beforeUnmount");
});onUnmounted(() => {console.log("unmounted");
});</script><style scoped>
.dialog-bg {position: fixed;top: 0;left: 0;width: 100vw;height: 100vh;text-align: center;
}
.dialog {width: 300px;padding: 20px;margin: 0 auto;margin-top: 200px;background-color: #e4e4e4;
}.btn-group {margin-top: 50px;display: flex;justify-content: space-around;
}
</style>

VUE路由

1.安装路由


在命令行中运行:


npm install vue-router@4

2.路由配置


在main.js 或者main.ts中添加路由配置


import { createApp } from 'vue'
import App from './App.vue'
//引入路由
import { createRouter, createWebHashHistory } from 'vue-router'//路由配置
let routes = [{ path: '/', component: () => import('../views/Login.vue') },{ path: '/test', component: () => import('../views/Test.vue') },
]const router = createRouter({history: createWebHashHistory(),routes
})let app = createApp(App);
app.use(router);//添加路由
app.mount('#app');

在App.vue中添加路由视图

template><router-view></router-view>
</template>

3.路由基本方法


参数的传递和获取

import { useRouter, useRoute } from 'vue-router'const router = useRouter()
const route = useRoute()//获取上层路由传递的参数function pushWithQuery(query) {//路由跳转router.push({name: 'search',query: { //传递query参数...route.query,//上一层路由参数},})
}

二级路由

App.vue

./views/Main.vue

PINIA的使用

官方网站https://pinia.vuejs.org/

1.安装pinia


在命令行中运行

npm install pinia

在main中添加pinia


import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia' //引入pinialet app = createApp(App);
app.use(createPinia());//注册使用pinia
app.mount('#app');

2.定义store


创建 TestStore.js 文件

import { defineStore } from 'pinia'
import { storeToRefs } from "pinia";//第一个参数test 相当于为 id ,并且它需要一个唯一名称
export const testStore = defineStore('test', {//state相当于data数据state: () => {return {count:0,};},//相当于方法methodsactions: {increment() {this.count++},},//相当于computed,计算属性getters: {testCount(state){return state.count * 2},}})

3.使用store


在vue文件中使用自定的store:

<template>
{{counter}}
<br/>
{{testCount}}<button @click="testClick">点我</button>
</template><script>import { testStore } from "./stores/TestStore";import { storeToRefs } from "pinia";//第一种使用方法const counter = testStore();//第二种使用方法:如果不使用storeToRefs,将会失去实时渲染let {count,testCount} = storeToRefs(counter)function testClick(){counter.increment();//或者count.value ++}</script>

相关文章:

vue3、vite、pinia 快速入门

准备 开发工具及插件IDE:vscode,WebStorm插件&#xff1a;Auto Close Tag、Auto Rename Tag、Live Server通过“&#xff01;”快速生成html模板正式学习安装vue通过CDN的方式导入vue<script src"" target"_blank">https://unpkg.com/vue3/dist/vue.…...

第六章 effect.scheduler功能实现

effect.scheduler功能实现 主要先了解scheduler需要实现什么样的需求&#xff0c;有一下四点&#xff1a; 1 通过 effect 的第二个参数给定一个 scheduler 的 fn 2 effect 第一次执行的时候 还会执行 fn 3 当 响应式对象 set update 不执行fn 而是执行 scheduler 4 如果说…...

软件测试之zentao

禅道 1. 禅道介绍 1.1 禅道项目管理软件是做什么的&#xff1f; 禅道&#xff0c;国产开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体&#xff0c;是一款专业的研发项目管理软件&#xff0c;完整覆盖了研发项目管理的核心流程。禅…...

美颜sdk动态贴纸的实现流程

随着移动互联网时代的到来&#xff0c;各式各样的 APP层出不穷&#xff0c;从最初的微信、 QQ到如今的抖音、快手等等&#xff0c;再到如今的微博、小红书等等&#xff0c;各式各样的 APP不断涌现。从最开始简单的图片展示到视频聊天&#xff0c;再到现如今丰富多样的各种动态贴…...

Web连接器

分模块编写爬虫&#xff08;一&#xff09; 连接器模块基本思路&#xff1a; 输入&#xff1a;url连接输出&#xff1a;url对应的html文本步骤&#xff1a; 定义url和user-agent获取网页的requests对象捕获异常&#xff1a; 403&#xff1a;禁止访问404&#xff1a;页面失效5…...

插上数据的翅膀,开启我升职加薪的梦想之旅

我是麦思思&#xff0c;大学毕业后就进入大厂工作并担任电子消费行业业务部门的数据分析师&#xff0c;对于一个数据分析师而言&#xff0c;Excel是必备技能&#xff0c;函数公式我能随手就来&#xff0c;几十M的文件处理那都是轻轻松松。但是&#xff0c;近几年随着企业业务发…...

来香港饮茶吹水先,免费报名Zabbix Meetup香港站!

Zabbix Meetup 来到香港啦&#xff01; 春暖花开&#xff0c;Zabbix计划5月来到香港&#xff0c;和你一起饮茶吹水&#xff01; 时间&#xff1a;5月某日&#xff0c;周几方便&#xff1f; 预计14:00-17:00 形式&#xff1a;线下交流会&#xff0c;免费&#xff0c;线下&…...

李群李代数求导-常用求导公式

参考 A micro Lie theory for state estimation in robotics manif issues 116 常用求导公式 Operation左雅克比右雅克比X−1\mathcal{X}^{-1}X−1JXX−1−I\mathbf{J}_{\mathcal{X}}^{\mathcal{X}^{-1}}\mathbf{-I}JXX−1​−IJXX−1−AdX\mathbf{J}_{\mathcal{X}}^{\mathc…...

IIS之web服务器的安装、部署以及使用教程(图文详细版)

WEB服务器的部署 打开虚拟机后查看已经开放的端口&#xff0c;可以看到没有TCP 80、TCP 443&#xff0c;说明HTTP服务端口没有打开 打开我的电脑—双击CD驱动器 选择安装可选的Windows组件 选择应用程序服务器—打开Internet信息服务—选择万维网服务和FTP服务 一路确…...

进程的介绍

文章目录一.进程的概念1.1概念1.2进程的组成1.2.1 PCB中描述进程的特征二.进程的虚拟地址空间三.进程间的通信引入线程一.进程的概念 1.1概念 百科的介绍: 换句话说,一个跑起来的程序,就是一个进程,也就是在操作系统中运行的exe程序就是一个进程,如下图的进程列表 进程是操…...

hadoop shell 练习题

hadoop shell 练习题: 利用Hadoop提供的Shell命令完成以下任务(路径中的xxx替换为自己的用户名)&#xff1a; 1、显示HDFS中指定的文件的读写权限、大小、创建时间、路径等信息&#xff1b; 示例: hdfs dfs -ls / 2、从HDFS中下载指定文件&#xff1b; 示例: hdfs dfs -get /…...

优化Linux系统性能的必杀技:调整进程优先级!学会使用nice命令,让你的系统飞一般的顺畅!

文章目录前言一. nice命令介绍1.1 nice的介绍1.2 cpu资源的调度1.3 nice是控制内核吗&#xff1f;二. 语法格式及常用选项三. 参考案例3.1 将ls命令的优先级调整为最高3.2 将 find 命令的优先级调整为最低3.3 如何查看nice值四. nice和renice的区别总结前言 大家好&#xff0c…...

fastdds router-3.开始

1. 项目概述 DDS路由器是由eProsima开发的跨平台非图形化应用程序&#xff0c;由Fast DDS提供支持&#xff0c;允许创建一个通信桥&#xff0c;连接两个DDS网络&#xff0c;否则将被隔离。DDS路由器的主要用途是通信两个物理或虚拟分离的DDS网络&#xff0c;这些网络属于不同的…...

云服务器ECS 什么是云服务器ECS?

云服务器ECS&#xff08;Elastic Compute Service&#xff09;是阿里云提供的性能卓越、稳定可靠、弹性扩展的IaaS&#xff08;Infrastructure as a Service&#xff09;级别云计算服务。 云服务器ECS免去了您采购IT硬件的前期准备&#xff0c;让您像使用水、电、天然气等公共…...

【socket网络编程】

socket网络编程主机字节序列和网络字节序列套接字地址结构通用socket地址结构专用的socket地址结构IP地址转换函数网络编程接口TCP编程流程代码举例服务器代码客户端服务器并发处理多个客户端多线程多进程主机字节序列和网络字节序列 主机字节序列分为大端模式和小端模式&…...

【验证码逆向专栏】某验三代、四代一键通过模式逆向分析

声明 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 本文章未经许可禁止转载…...

《MySql学习》 MySQL的 加锁规则

MySQL加锁原则 两个原则 原则 1&#xff1a;加锁的基本单位是 next-key lock。next-key lock 是前开后闭区间&#xff08;区间锁和行锁&#xff09;。原则 2&#xff1a;查找过程中访问到的对象&#xff08;索引&#xff09;才会加锁。 两个优化 1.优化 1&#xff1a;索引上…...

软件测试(linux命令篇-01文件操作命令)

linux文件篇命令linux系统常用文件操作命令1、查看目录内容及常用参数&#xff1a;ls2、目录切换&#xff1a;cd 3、创建文件&#xff1a;touch 4、创建目录 &#xff1a;mkdir5、 删除文件或目录&#xff1a;rm6、文件或目录的复制&#xff1a;cp7、文件或目录的移动&#xff…...

Code Virtualizer 3.1.4 Crack

Code Virtualizer 是一个强大的 Windows 应用程序代码混淆系统&#xff0c;它可以帮助开发人员保护他们的敏感代码区域免受逆向工程的影响&#xff0c;基于代码虚拟化的非常强大的混淆代码。 Code Virtualizer 会将您的原始代码&#xff08;Intel x86/x64 指令&#xff09;转换…...

Torch同时训练多个模型

20230302 引言 在进行具体的研究时&#xff0c;利用Torch进行编程&#xff0c;考虑到是不是能够同时训练两个模型呢&#xff1f;&#xff01;而且利用其中一个模型的输出来辅助另外一个模型进行学习。这一点&#xff0c;在我看来应该是很简单的&#xff0c;例如GAN网络同时训…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

面试高频问题

文章目录 &#x1f680; 消息队列核心技术揭秘&#xff1a;从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"&#xff1f;性能背后的秘密1.1 顺序写入与零拷贝&#xff1a;性能的双引擎1.2 分区并行&#xff1a;数据的"八车道高速公路"1.3 页缓存与批量处理…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...

基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究

摘要&#xff1a;在消费市场竞争日益激烈的当下&#xff0c;传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序&#xff0c;探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式&#xff0c;分析沉浸式体验的优势与价值…...

云原生安全实战:API网关Envoy的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口&#xff0c;负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...