惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
The GitHub Blog
The GitHub Blog
美团技术团队
Know Your Adversary
Know Your Adversary
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Register - Security
The Register - Security
Stack Overflow Blog
Stack Overflow Blog
Attack and Defense Labs
Attack and Defense Labs
G
Google Developers Blog
I
InfoQ
博客园 - 司徒正美
T
Troy Hunt's Blog
Google DeepMind News
Google DeepMind News
J
Java Code Geeks
MongoDB | Blog
MongoDB | Blog
博客园 - 聂微东
A
About on SuperTechFans
云风的 BLOG
云风的 BLOG
S
Security Affairs
M
MIT News - Artificial intelligence
Simon Willison's Weblog
Simon Willison's Weblog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
Tailwind CSS Blog
量子位
Vercel News
Vercel News
月光博客
月光博客
V
Vulnerabilities – Threatpost
N
News and Events Feed by Topic
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LangChain Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
LINUX DO - 最新话题
F
Full Disclosure
The Hacker News
The Hacker News
Hacker News: Ask HN
Hacker News: Ask HN
T
Tor Project blog
A
Arctic Wolf
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Forbes - Security
Forbes - Security
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Y
Y Combinator Blog
GbyAI
GbyAI
B
Blog RSS Feed
V
Visual Studio Blog
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs

Jiajun的技术笔记

你好,2026! TiDB 源码阅读(六):TiDB Coprocessor 源码解析 性能优化的核心思想 TiDB 源码阅读(五):索引 TiDB 源码阅读(四):AST、逻辑计划、物理计划 CockroachDB Serverless Architecture podman 无故退出 Cursor Control-L (CTRL-L) Keyboard Shortcuts in Terminal Replace docker with podman Using xmonad with xfce4 A RC script for freebsd frpc 自己动手写一个k8s controller AI 会取代你的(编程)岗位吗? 自建DERP服务器提升Tailscale连接速度(使用Nginx转发) 自动升级Docker容器 再读《程序员修炼之道-从小工到专家》 让浏览器下载文件 再读《软件随想录》/《黑客与画家》/《软技能》 HTTP 压力测试中的 Coordinated Omission 2的补码 编程语言中的 context 是什么? flutter macOS 构建出错 Flatpak 使用小记 Golang CAS 操作是怎么实现的 PostgreSQL 当MQ来使用 Clash 结合 工作VPN 的网络设计 使用 PostgreSQL 搭建 JuiceFS PostgreSQL 配置优化和日志分析 有GitHub Copilot?那就可以搭建你的ChatGPT4服务 窗口函数的使用(以PG为例) 读《为什么学生不喜欢上学》 OpenAI Prompt Engineering 摘录和总结 读《打造真正的新产品》 Linux 自动挂载 alist 提供的webdav FreeBSD 使用 vm-bhyve 安装Debian虚拟机 FreeBSD 和 Linux 网卡聚合实现提速 GPT 帮我搞定了时区转换问题 长任务系统如何处理? macOS/Linux 编译 InputLeap 使用开源软KVM - synergy-core 解决 macOS 终端hostname一直变化问题 KVM 共享 Intel 集成显卡 PromQL 备忘 读《格鲁夫给经理人的第一课》 读《打开心智》 为什么要把复杂的联表操作拆成多个单表查询? 红包系统的设计 MySQL Index Condition Pushdown Optimization Go mod 简明教程 OpenWRT 使用 Android/iOS USB 网络 搭建旁路由 Golang gRPC 错误处理 编写可维护的单元测试代码 OAuth 2 详解(六):Authorization Code Flow with PKCE OAuth 2 详解(五):Device Authorization Flow OAuth 2 详解(三):Resource Owner Password Credentials Grant OAuth 2 详解(四):Client Credentials Flow OAuth 2 详解(二):Implict Grant Flow OAuth 2 详解(一):简介及 Authorization Code 模式 ElasticSearch 学习笔记 三种git流程以及发版模型 错误处理实践 权限模型(RBAC/ABAC) OIDC(OpenID Connect) 简介 任务队列简介 PostgreSQL 操作笔记 使用Drone CI构建CI/CD系统 Golang migrate 做数据库变更管理 使用PostgreSQL做搜索引擎 Nginx 源码阅读(三): 连接池、内存池 Nginx 源码阅读(二): 请求处理 Nginx 源码阅读(一): 启动流程 Go 泛型简明教程 KVM 显卡穿透给 Windows 使用 HTTP Router 处理 Telegram Bot 按钮回调 使用反射(reflect)对结构体赋值 GIN 是如何绑定参数的 你好 2022(2021 年终总结) 用Go导入大型CSV到PostgreSQL 使用 OpenWRT 搭建软路由 使用软KVM切换器 barrier 共享键鼠 SQL 防注入及原理 使用 gomock 测试 Go 代码 gevent不是黑魔法(二): gevent 实现 gevent不是黑魔法(一): greenlet 实现 用 entgo 替代 gorm 应用内使用crontab不是那么方便 单测时要不要 mock 数据库? Sentry 自建指南 用selenium完成自动化任务 用闲置的安卓手机做垃圾电话短信过滤 推荐三个时间管理工具 一次事故反思 当JS遇到uint64:JS整数溢出问题 SQLite3 存储以及ACID原理 Redis源码阅读:pub/sub实现 Redis源码阅读:zset实现 Redis源码阅读:bitmap 位图的运算 Redis源码阅读:set是怎么做交并集运算的? Redis源码阅读:list实现(ziplist, quicklist)
VueJS 总结
Jiajun Huang · 2023-12-17 · via Jiajun的技术笔记

使用Vue有一段时间了,可能因为使用场景比较少,一直都感觉不得要领,最近终于有一种融会贯通的感觉了,理解了大部分使用场景 和技巧。这篇文章是我的总结。

简单示例

比起官网的写法,对于后端开发人员来说,我觉得新式的 Composition API + Single File Components 的写法会更容易让人理解, 这是一个例子:

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>

<style scoped>
button {
  font-weight: bold;
}
</style>
  • <script setup></script> 部分,就是JS逻辑处理的内容
  • <template></template> 部分,就是模板内容,在里面写页面的模块,比如表单、按钮、弹窗等等
  • <style scoped></style> 部分,就是CSS样式

每一个页面,对应一个 Single File Components 文件,比如 main.vue / home.vue 等等。

构建工具

前端需要使用构建工具,可以提高开发效率,以前大部分都是使用 yarn,现在比较流行一个新型的工具,叫做 vite,使用方法如下:

$ npm create vite@latest

执行完成之后,照着提示一步步操作就可以,对于Vue项目,就选择Vue,然后选择JS或者TS。

项目结构

初始化完成之后,就可以看到如下的一个结构:

demovite $ tree
.
├── index.html
├── package.json
├── public
│   └── vite.svg
├── README.md
├── src
│   ├── App.vue
│   ├── assets
│   │   └── vue.svg
│   ├── components
│   │   └── HelloWorld.vue
│   ├── main.js
│   └── style.css
└── vite.config.js

5 directories, 10 files

其实渲染以后,浏览器首先加载的仍然是 index.html,我们来看看内容:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + Vue</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

可以看到 body 里,有一个div,id是 app,紧接着就是执行路径为 /src/main.js 的JS:

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

createApp(App).mount('#app')

这段JS的内容很好理解,import部分就和后端的语言里的导入是一样的,真正执行的地方,就是 createApp(App).mount('#app'), 这里就是找到id为 app 的DOM元素,然后开始执行代码操作DOM渲染页面。

而我们这里,App.vue 就是第一个页面:

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <div>
    <a href="https://vitejs.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <HelloWorld msg="Vite + Vue" />
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

这里就可以看到我们最上面描述的三个段落:<script setup></script>, <template></template>, <style scoped></style>

Vue UI 框架

鉴于我们是后端,写UI自然是不太熟悉的,因此我们需要一个UI框架,这样我们可以直接使用里面提供的UI组件,不需要自己去改样式。 Vue常用的就是这么几个:

  • element-plus 饿了么出品的,饿了么风格的UI
  • Vuetify Material Design 风格的UI
  • BootstrapVue 使用Bootstrap的UI
  • Ant Design Vue Ant Design 风格的UI

这个就看个人喜好,选择一个就可以。

VueJS 语法简介

变量

VueJS是一个前端的MVVM框架,啥意思呢?就是以前我们需要执行JS去更改DOM,这样UI才会发生变化,但是现在,我们可以直接改变内存 中的一个变量,VueJS会自动将变量的值结合模版,然后自动更改DOM。这个只有使用了才能感受出来,开发效率真的高很多。

并不是任意变量VueJS都能监听到变化的,必须是它包装的或者支持的,下面这些就是了:

  • ref: 比如 const count = ref(0),只要 count.value 发生了变化,他就会监测到
  • reactive: 和ref一样,不过reactive是直接监听一个object,而且使用的时候,可以直接用,而不需要像ref那样使用 count.value。例如:const state = reactive({ count: 0 }),直接使用 state.count 即可

这两个的文档在 https://vuejs.org/guide/essentials/reactivity-fundamentals.html 请一定仔细阅读。

模板语法

对于后端开发来说,尤其是使用过后端的模版引擎的开发者来说,应该不难,参考文档 https://vuejs.org/guide/essentials/template-syntax.html 直接写HTML,在需要使用变量的地方,使用双括号即可:

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

使用冒号来绑定属性,例如 <div v-bind:id="dynamicId"></div>,可以简写为 <div :id="dynamicId"></div>

使用 @ 来监听事件:

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

<!-- shorthand -->
<a @[eventName]="doSomething">

使用 v-if, v-else, v-else-if, v-show 来进行条件渲染。

computed 和 watch

有一些变量需要根据别的变量计算,才能得到值,或者一个变量变化的时候,我们希望另一个变量跟着变化,这个时候,就需要使用 computed

而有时候我们希望监听某个值,当然发生了变化,我们进行一些操作,这个时候就使用 watch,我们来看看GPT对他两的对比和总结:

Computed Properties (计算属性):

定义: 计算属性是基于它们的依赖进行计算的响应式属性。当依赖项发生变化时,计算属性会重新计算。 用途: 主要用于数据的转换和组合。例如,从原始数据派生出新的数据。 缓存: 计算属性是基于它们的响应式依赖进行缓存的。只有当依赖项发生变化时,计算属性才会重新计算。这意味着只要依赖项保持不变,多次访问计算属性会立即返回之前的计算结果,而不会重新执行函数。 示例场景: 如根据用户的名和姓计算出一个完整的姓名。 Watchers (侦听器):

定义: 侦听器用于观察和响应 Vue 实例上数据的变化。当侦听的数据变化时,会执行一个回调函数。 用途: 主要用于执行数据变化时的副作用(side effects),如异步操作或较长的运算。 方式: 侦听器不会返回一个值,而是在数据变化时执行代码。 示例场景: 如在用户更改数据后发送 AJAX 请求。 总结:

用途区别: computed 用于计算值的派生和转换,而 watch 用于响应数据的变化执行异步操作或昂贵的操作。 性能考虑: computed 属性由于其缓存特性,对于性能要求较高的场景更合适。 应用场景: 选择 computed 还是 watch 取决于具体的应用场景和需求。对于任何可以用计算属性实现的功能,优先考虑使用计算属性,只有在需要执行异步操作或复杂逻辑时才使用侦听器。

路由

页面之间如果需要跳转咋办呢?这个时候就需要一个路由框架,对于Vue的项目来说,一般都是使用 vue-router

// 1. Define route components.
// These can be imported from other files
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }

// 2. Define some routes
// Each route should map to a component.
// We'll talk about nested routes later.
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
]

// 3. Create the router instance and pass the `routes` option
// You can pass in additional options here, but let's
// keep it simple for now.
const router = VueRouter.createRouter({
  // 4. Provide the history implementation to use. We are using the hash history for simplicity here.
  history: VueRouter.createWebHashHistory(),
  routes, // short for `routes: routes`
})

// 5. Create and mount the root instance.
const app = Vue.createApp({})
// Make sure to _use_ the router instance to make the
// whole app router-aware.
app.use(router)

app.mount('#app')

// Now the app has started!

状态管理

前端需要管理一些状态,比如登陆状态,对于这类需求,一般使用 vuex,现在最新版的,就是 pinia

总结

以上就是我对VueJS知识的理解和整理,只是一个大纲,具体的内容,其实是需要每个文档都读一遍,写一遍,理解一遍才能 真正掌握的。


Refs: