vue3、vite、pinia 快速入门

news2024/9/28 21:26:09

准备 开发工具及插件

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 event
      if (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 共存。当有如下模板:

<div
  class="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:true
     text: {
   //此时旧数据不记录,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-dialog
    v-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) // 0

counter.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>
        <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 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' //引入pinia

let 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,
        };
      },
    //相当于方法methods
    actions: {
        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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/381568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql数据库之索引分类

分类含义特点关键字主键索引针对于表中主键创建的索引默认自动创建&#xff0c;只能有一个primary唯一索引避免同一个表中某数据列中的值重复可以有多个unique常规索引快速定位特定数据可以有多个全文索引全文索引查找的是文本中的关键词&#xff0c;而不是比较索引中的值可以有…

01 Android基础--广播

01 Android基础--广播什么是广播&#xff1f;广播的分类本地广播LocalBroadcastManager什么是广播&#xff1f; 传输信息的机制。 主要记住三个要素&#xff1a;1.广播(Broadcast) - 用于发送广播; 2.广播接收器(BroadcastReceiver) - 用于接收广播&#xff1b;3.意图内容(Inte…

【活学活用掌握trap命令】

trap 命令用于指定在接收到信号后将要采取的动作&#xff0c;常见的用途是在脚本程序被中断时完成清理工作。当 shell 接收到 sigspec 指定的信号时&#xff0c; arg 参数(通常是执行命令)会被读取&#xff0c;并被执行。 1. 命令介绍 开始掌握基本的使用方式和方法 [1] 语法…

云计算简介

本文为copy他人编写的文档&#xff0c;由于不确认作者名称&#xff0c;故无法标记来源&#xff08;实际来源是群pdf文档&#xff09;&#xff0c;暂时发文为原创&#xff0c;因为无法贴出原文链接&#xff01; 云原生的前世今生 随着公有云和私有云的广泛部署&#xff0c;云计…

1.1 Linux开发环境搭建

1. Ubuntu服务器安装ssh工具&#xff0c;然后使用xshell连接 查看Ubuntu服务器的IP地址时&#xff0c;如果ifconfig失败&#xff0c;需要先安装一下net工具 sudo apt install openssh-server sudo apt install net-tools2. 打开vscode&#xff0c;安装Remote Development拓展…

操作系统——11.线程概念和多线程模型

这篇文章我们来讲一下操作系统中的线程概念和多线程模型 目录 1.概述 2.线程 2.1问题提出 2.2线程概念 2.3带来的变化 2.4线程的属性 2.5线程的实现方式 2.5.1用户级线程 2.5.2内核级线程 2.5.3相互组合 2.6多线程模型 2.6.1多对一模型 2.6.2一对一模型 2.6.3多…

操作系统权限提升(二十二)之Linux提权-SUDO滥用提权

系列文章 操作系统权限提升(十八)之Linux提权-内核提权 操作系统权限提升(十九)之Linux提权-SUID提权 操作系统权限提升(二十)之Linux提权-计划任务提权 操作系统权限提升(二十一)之Linux提权-环境变量劫持提权 SUDO滥用提权 SUDO滥用提权原理 sudo是linux系统管理指令&…

【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序

避坑宝 v1.0.0 基于SpringBootuniapp企业黑红名单吐槽小程序 &#x1f4da;项目介绍 避坑宝 【避坑宝】企业黑红名单吐槽小程序是一个具有吐槽发布企业信息的一个平台&#xff0c;言论自由&#xff0c;评判自定&#xff0c;便于我们打工人分辨企业好坏。技术栈基于SpringBoot…

墨者靶场--报错盲注

引入一下报错注入的知识点&#xff0c;参考【https://www.cnblogs.com/X-caiji/p/13186633.html】 输入测试语句1 and 11--,正常回显 1 and 12-- 无任何报错信息&#xff0c;但是可以确定我们输入的内容确实是被执行了。 那么可以考虑是盲注 一般在实战过程中就需要考虑各种各…

Elasticsearch集成之(Spring Data Elasticsearch)

Elasticsearch集成之&#xff08;Spring Data Elasticsearch&#xff09; 1、Spring Data 框架介绍 Spring Data 是一个用于简化数据库、非关系型数据库、索引库访问&#xff0c;并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷&#xff0c;并支持 map-re…

php宝塔搭建部署实战织梦响应式人力资源网站模板源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套php开发的织梦响应式人力资源网站模板源码。感兴趣的朋友可以自行下载学习。 技术架构 PHP7 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码&#xff0c;宝塔…

线下实践阿里云:「 云原生技术实践营 - 容器微服务专场 」

一、前言 自己在杭州工作和生活也有将近10年&#xff0c;由于有些前同事和朋友在阿里上班&#xff0c;也过去玩过几次。在印象中&#xff0c;作为联谊公司&#xff0c;还和阿里组织过一些小规模的活动&#xff0c;比如相亲和篮球比赛。 所以&#xff0c;对阿里杭州的滨江园区和…

2023年最新人工智能入门指南(学习清单)

ChatGPT最近很火&#xff0c;为了帮助想入门人工智能的小伙伴们准备了一份超详细的学习清单 前言 为帮助大家快速入门机器学习、深度学习&#xff0c;根据我自己多年的学习和工作经验&#xff0c;总结了这份保姆级的学习清单&#xff0c;让大家在学习时不走弯路。 这份清单主…

抽象队列同步器AQS应用lock详解

目录 AQS应用之Lock 并发之父 ReentrantLock 整体实现思路 AQS具备特性 同步等待队列 条件等待队列 AQS源码分析 AQS应用之Lock 并发之父 生平不识Doug Lea&#xff0c;学懂并发也枉然 Java并发编程核心在于java.util.concurrent包而juc当中的大多数同步器实现都是围绕…

linux 环境 postgresql + postgis 安装

postgis 是 postgresql 的一个扩展插件&#xff0c;具有强大的空间计算功能&#xff0c;很适合用于地图系统。本次演示使用的操作系统为CentOS Linux release 7.9.2009 (Core)postgis 下载登录 postgis 的官方网站&#xff1a;http://postgis.net/下载符合 postgresql 数据库版…

ShardingSphere官方文档感悟

ShardingSphere官方文档感悟什么是ShardingSphereShardingSphere-JDBCShardingSphere-Proxy功能产品优势设计哲学连接增强可插拔L1内核层L2功能层L3生态层部署形态ShardingSphere-JDBC独立部署ShardingSphere-Proxy独立部署混合部署架构官网地址&#xff1a; https://shardings…

HTTP的前世今生

承接上文HTTP请求的详细过程http协议版本历史http造就了万维网&#xff0c;http成就了互联网第三次信息技术革命并且影响着即将到来的第四次人工智能技术革命。1989年第一个http协议&#xff0c;http0.9发布&#xff0c;发明了万维网&#xff0c;创建了世界第一个网页浏览器&am…

软件测试面试必杀篇:【2023软件测试面试八股文宝典】

800道软件测试面试真题&#xff0c;高清打印版打包带走&#xff0c;横扫软件测试面试高频问题&#xff0c;涵盖测试理论、Linux、MySQL、Web测试、接口测试、App测试、Python、Selenium、性能测试、LordRunner、计算机网络、数据结构与算法、逻辑思维、人力资源等模块面试题&am…

Jinja2----------过滤器的使用、控制语句

目录 1.过滤器的使用 1.过滤器和测试器 2.过滤器 templates/filter.html app.py 效果 3.自定义过滤器 app.py templates/filter.html 效果 2.控制语句 1.if app.py templates/control.html 2.for app.py templates/control.htm 1.过滤器的使用 1.过滤器和测…

在linux中配置环境变量

1. 环境变量的作用 环境变量是操作系统在运行的时候&#xff0c;记录的一些关键性信息&#xff0c;用于辅助系统的运行。 在linux中执行 evn 命令即可查看当前系统中记录的环境变量。 环境变量是一种KeyValue结构 2. 符号$ 在linux系统中&#xff0c;$&#xff0c;用于取“…