【前端】Vue一本通 ESLint JSX

近几天更新完毕,不定期持续更新,建议关注收藏点赞。


目录

  • 工具推荐
    • vscode插件
    • vue-devtools
    • ESLint
  • JSX语法扩展
  • 简介
    • 设计模式
    • 快速入门
  • @vue/cli脚手架
  • 使用
    • vue指令

工具推荐

工欲善其事,必先利其器。

vscode插件

Vetur:vue代码高亮插件
VueHelper:代码提示插件

vue-devtools

vue-devtools 是一个专门为 Vue.js 开发者打造的 浏览器开发者工具插件,可以用来 调试、查看和修改 Vue 应用的内部状态。
简单来说,它就像给 Vue 应用装了个“透视眼”,让你能轻松看到组件之间是怎么工作的。

  • vue-devtools 能干嘛?【5点】
    查看组件结构:类似一棵树,展示你的应用是由哪些组件组成的,谁嵌套谁。你可以直接点进每个组件,看到它的名字、props、data、computed 等。
    实时查看和修改数据:能看到组件当前的数据(data、props、computed)。修改数据还能立刻看到页面更新,适合调试。
    事件追踪:查看哪个组件发出了哪个自定义事件($emit)。可以看到事件的名字、参数、传播链等。
    Vuex 调试(如果你用了 Vuex):查看 Vuex 的 state、getters、mutations、actions。
    时间旅行调试(Time Travel Debugging):可以前进后退查看状态变化。
    性能检测(性能分析标签页):查看组件的更新频率、渲染开销,找出性能瓶颈。
  • 安装
    Chrome 插件商店搜索 vue-devtools 安装。或者在 Firefox 也可以装。
    如果是开发桌面应用或在本地调试,Vue 官方还提供了独立版(Electron 应用)。
  • 使用
    确保你的 Vue 应用在开发模式Vue 在生产模式下默认关闭调试信息,vue-devtools 可能检测不到。所以开发时要确保没有 Vue.config.productionTip = false 或类似压缩优化设置。

ESLint

它是一个代码检查工具,用于JavaScript 和 TypeScript 的静态代码分析工具,主要功能是识别并修复代码中的问题,比如语法错误、不一致的风格、潜在的 bug 等。

npm install eslint --save-dev
npx eslint --init #初始化配置
#这个命令会引导你选择项目的风格、使用的框架(React、Vue等)、
#是否使用 TypeScript 等,并生成一个配置文件(.eslintrc.js、.eslintrc.json 等)。
npx eslint yourfile.js #检查这个文件
npx eslint yourfile.js --fix #自动修复代码

比如:如果在main.js 声明个变量而不使用,则终端和网页都会报错,因为不严谨。

  • 解决方式
    方式1: 手动解决掉错误, 以后项目中会讲如何自动解决
    方式2: 暂时关闭eslint检查, 在vue.config.js中配置后重启服务
module.exports={//其他配置略lintOnSave:false//关闭eslint检查
}
  • 常配合使用的插件/配置
    eslint-config-airbnb: Airbnb 代码规范
    eslint-plugin-react: 检查 React 项目
    eslint-plugin-import: 管理模块导入
    eslint-config-prettier: 配合 Prettier,关闭 ESLint 中和 Prettier 冲突的规则

JSX语法扩展

JSX(JavaScript XML)是一种 JavaScript 的语法扩展,主要用于Vue/ React。它让你可以在 JavaScript 中写出类似 HTML 的代码,描述界面的结构。
Vue 本身没有默认使用 JSX,默认用的是模板语法(.vue 文件里的 < template>),但支持 JSX 语法扩展

function Welcome(props) {return <h1>Hello, {props.name}</h1>;
}const element = <Welcome name="Alice" />;
  • JSX 的核心特点
  1. 像 HTML 但不是 HTML
const name = "ChatGPT";
const element = <h1>Hello, {name}!</h1>;
  1. 标签必须闭合
// 正确
<img src="logo.png" />
  1. 只能有一个根节点
// 错误 ❌
return (<h1>Title</h1><p>Description</p>
);// 正确 ✅
return (<div><h1>Title</h1><p>Description</p></div>
);
  1. class 改为 className
    因为 class 是 JavaScript 的关键字,所以在 JSX 中写样式类时要用 className
<div className="container">Hello</div>
  • JSX 配合 ESLint
    为了让 ESLint 正确识别 JSX,你需要使用对应的插件和解析器:
#react
npm install eslint-plugin-react eslint-plugin-react-hooks --save-dev#vue
npm install --save-dev eslint eslint-plugin-vue @vue/eslint-config-standard babel-eslint eslint-plugin-babel eslint-plugin-import eslint-plugin-node eslint-plugin-promise#vue3还需要
npm install @vitejs/plugin-vue-jsx @vue/babel-plugin-jsx --save-dev
//配置 .eslintrc.js 示例
//react
module.exports = {parser: 'babel-eslint',extends: ['eslint:recommended','plugin:react/recommended'],plugins: ['react'],rules: {'react/prop-types': 'off'},settings: {react: {version: 'detect'}}
};//vue
module.exports = {root: true,env: {node: true,},parserOptions: {parser: 'babel-eslint',ecmaVersion: 2020,sourceType: 'module',ecmaFeatures: {jsx: true, // 开启 JSX 支持},},extends: ['eslint:recommended','plugin:vue/vue3-recommended', // Vue 3 推荐配置'plugin:import/recommended','plugin:promise/recommended',],plugins: ['vue', 'babel'],rules: {// 自定义规则,例如关闭 console 警告'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off','no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',// Vue 特有规则'vue/no-multiple-template-root': 'off', // Vue 3 不再强制单根节点},
};//babel.config.js
module.exports = {presets: ['@vue/cli-plugin-babel/preset'],plugins: ['@vue/babel-plugin-jsx'],
};//Vue 组件中使用 JSX
<script setup>
import { defineComponent } from 'vue';export default defineComponent({setup() {return () => <div class="hello">Hello from JSX!</div>;},
});
</script>

简介

vue的底层还是原生js。开发更加的效率和简洁, 易于维护, 现在很多项目都是用vue开发的。
渐进式声明式组件化的javacript框架,官网地址: https://cn.vuejs.org/ 。
渐进式: 逐渐进步, 想用什么就用什么, 不必全都使用

  • vue的特点:
    • 渐进式
    • 声明式渲染:ue 基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。
    • 数据驱动视图 (响应式):Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM。
    • 极少的去写DOM操作相关代码
    • 双向绑定
    • 组件系统
    • 不兼容IE8及以下浏览器(因为vue的响应式原理是基于es5的Object.defineProperty(),而这个方法不支持ie8及以下)
  • 库 v.s. 框架
    库: 封装的属性或方法 (例jquery.js),还是那个规则、语法、元素。
    框架: 拥有自己的规则和元素, 比库强大的多 (例vue.js)
  • 工程化开发方式:在webpack环境中开发vue,这是最推荐的企业常用方式
  • 目前Vue2已停止维护,之后所有Vue3的变化都用高亮显示
    最简单的实例
<div id="app"><button @click="count++">Count is: {{ count }}</button>
</div>
import { createApp, ref } from 'vue'createApp({setup() {return {count: ref(0)}}
}).mount('#app')

设计模式

  • vue是MVVM设计模式
    vue源码内采用MVVM设计模式思想, 大大减少了DOM操作, 提高开发效率
    用数据驱动视图改变, 操作dom的事,由vue源码内部来做。vue是数据变化视图自动更新, 减少操作DOM时间, 提高开发效率
  1. 在vue中,不推荐直接手动操作DOM!!!
  2. 在vue中,通过数据驱动视图,不要在想着怎么操作DOM,而是想着如何操作数据!!(思想转变)
    • MVVM
      MVVM,一种软件架构模式,决定了写代码的思想和层次
      M: model数据模型 (data里定义)
      V: view视图 (html页面)
      VM: ViewModel视图模型 (vue.js源码)
      在这里插入图片描述
      在这里插入图片描述
      MVVM通过数据双向绑定让数据自动地双向同步 不再需要操作DOM
      V(修改视图) -> M(数据自动同步)
      M(修改数据) -> V(视图自动同步)

M层和V层可以互相改变
在devtool工具可以改变M层的变量, 观察V层(视图的自动同步);(devtool工具就是chrome浏览器检查工具(开发者模式)里多出来的vue工具)

  • 对比MVC设计模式
    • 组件化:模块独立,复用性强,适用于所有现代前端项目,如React, Vue
    • Flux/Redux:单向数据流,适合大型状态管理,见于react
    • MVC: 也是一种设计模式, 组织代码的结构, 是model数据模型, view视图, Controller控制器, 在控制器这层里编写js代码, 来控制数据和视图关联
      应用于早期小项目
    • MVVM: 即Model-View-ViewModel的简写。即模型-视图-视图模型, VM是这个设计模式的核心, 连接v和m的桥梁, 内部会监听DOM事件, 监听数据对象变化来影响对方. 我们称之为数据绑定
      应用于Vue, Angular 等现代框架,响应式数据双向绑定

React 并不严格是 MVVM,为什么很多人还是说 React 属于 MVVM?因为它也有:Model(state、props)、View(JSX)、某种“中间层逻辑”(用 Hook、useEffect 实现的)但这些功能都融合在组件中,不像 Vue 的 ViewModel 那么清晰分层。
React 是一种以组件为中心、函数式编程风格、支持单向数据流的前端库。它既不像传统 MVC,也不是典型 MVVM,而是一种组件驱动的 UI 架构。
React 的不同点:

  1. React 是单向数据流
    数据从组件的 state/props 向下流动到 UI。
    没有像 Vue 那样的“自动双向绑定”。
  2. 没有“真正意义上的 ViewModel”
    在 React 中,没有一个专门处理逻辑与数据绑定的“ViewModel”。
    组件本身就承担了“视图”和“一部分逻辑”的职责。
  3. React 强调函数式思想
    使用 Hook 来组合逻辑,而不是 ViewModel。
    倾向于将 UI 表现为“状态的纯函数”。

快速入门

  • 单文件组件
    使用一种类似 HTML 格式的文件来书写 Vue 组件,它被称为单文件组件 (也被称为 *.vue 文件,英文 Single-File Components,缩写为 SFC)。顾名思义,Vue 的单文件组件会将一个组件的逻辑 (JavaScript),模板 (HTML) 和样式 (CSS) 封装在同一个文件里。
//app.vue
<script setup>
import { ref } from 'vue'
// “ref”是用来存储值的响应式数据源。
const count = ref(0)
</script><template><button @click="count++">Count is: {{ count }}</button>
</template><style scoped>
button {font-weight: bold;
}
</style>//更复杂的例子
<!--
这个示例展示了如何通过 v-on 指令处理用户输入。
--><script setup>
import { ref } from 'vue'const message = ref('Hello World!')function reverseMessage() {// 通过其 .value 属性// 访问/修改一个 ref 的值。message.value = message.value.split('').reverse().join('')
}function notify() {alert('navigation was prevented.')
}
</script><template><!--注意我们不需要在模板中写 .value,因为在模板中 ref 会自动“解包”。--><h1>{{ message }}</h1><!--绑定到一个方法/函数。这个 @click 语法是 v-on:click 的简写。--><button @click="reverseMessage">Reverse Message</button><!-- 也可以写成一个内联表达式语句 --><button @click="message += '!'">Append "!"</button><!--Vue 也为一些像 e.preventDefault() 和 e.stopPropagation()这样的常见任务提供了修饰符。--><a href="https://vuejs.org" @click.prevent="notify">A link with e.preventDefault()</a>
</template><style>
button, a {display: block;margin-bottom: 1em;
}
</style>//attribute绑定
<!--
现在我们将元素的 attribute / property 响应式地绑定到状态上。
这个 :title 语法是 v-bind:title 的简写。
--><script setup>
import { ref } from 'vue'const message = ref('Hello World!')
const isRed = ref(true)
const color = ref('green')function toggleRed() {isRed.value = !isRed.value
}function toggleColor() {color.value = color.value === 'green' ? 'blue' : 'green'
}
</script><template><p><span :title="message">Hover your mouse over me for a few seconds to see my dynamically bound title!</span></p><!--除了普通字符串之外,class 绑定还特别支持了对象和数组--><p :class="{ red: isRed }" @click="toggleRed">This should be red... but click me to toggle it.</p><!-- 样式绑定也支持对象和数组 --><p :style="{ color }" @click="toggleColor">This should be green, and should toggle between green and blue on click.</p>
</template><style>
.red {color: red;
}
</style>//条件&循环
<!--
我们可以通过 v-if 和 v-for 指令条件性地或循环地渲染内容。
--><script setup>
import { ref } from 'vue'const show = ref(true)
const list = ref([1, 2, 3])
</script><template><button @click="show = !show">Toggle List</button><button @click="list.push(list.length + 1)">Push Number</button><button @click="list.pop()">Pop Number</button><button @click="list.reverse()">Reverse List</button><ul v-if="show && list.length"><li v-for="item of list">{{ item }}</li></ul><p v-else-if="list.length">List is not empty, but hidden.</p><p v-else>List is empty.</p>
</template>//表单绑定
<!--
我们可以使用 v-model 指令在状态和表单输入之间创建双向绑定。
--><script setup>
import { ref } from 'vue'const text = ref('Edit me')
const checked = ref(true)
const checkedNames = ref(['Jack'])
const picked = ref('One')
const selected = ref('A')
const multiSelected = ref(['A'])
</script><template><h2>Text Input</h2><input v-model="text"><p>{{ text }}</p><h2>Checkbox</h2><input type="checkbox" id="checkbox" v-model="checked"><label for="checkbox">Checked: {{ checked }}</label><!--多个复选框可以绑定到相同的 v-model 数组--><h2>Multi Checkbox</h2><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><p>Checked names: {{ checkedNames }}</p><h2>Radio</h2><input type="radio" id="one" value="One" v-model="picked"><label for="one">One</label><br><input type="radio" id="two" value="Two" v-model="picked"><label for="two">Two</label><p>Picked: {{ picked }}</p><h2>Select</h2><select v-model="selected"><option disabled value="">Please select one</option><option>A</option><option>B</option><option>C</option></select><p>Selected: {{ selected }}</p><h2>Multi Select</h2><select v-model="multiSelected" multiple style="width:100px"><option>A</option><option>B</option><option>C</option></select><p>Selected: {{ multiSelected }}</p>
</template>
  • vue组件风格:两种不同的风格书写:选项式 API 和组合式 API。
    在生产项目中:当你不需要使用构建工具,或者打算主要在低复杂度的场景中使用 Vue,例如渐进增强的应用场景,推荐采用选项式 API。
    当你打算用 Vue 构建完整的单页应用,推荐采用组合式 API + 单文件组件。
  • 组合式 API (Composition API)
    通过组合式 API,我们可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与<script setup>搭配使用。这个 setup attribute 是一个标识,告诉 Vue 需要在编译时进行一些处理,让我们可以更简洁地使用组合式 API。比如,<script setup> 中的导入和顶层变量/函数都能够在模板中直接使用。
<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>
  • 选项式 API (Options API)
    用包含多个选项的对象来描述组件的逻辑,例如 data、methods 和 mounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。
<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>
  • 简单组件 多文件
//app.vue
<!--
这里展示了最简单的组件,它接收一个 prop 并渲染出来。
--><script setup>
import { ref } from 'vue'
import TodoItem from './TodoItem.vue'const groceryList = ref([{ id: 0, text: 'Vegetables' },{ id: 1, text: 'Cheese' },{ id: 2, text: 'Whatever else humans are supposed to eat' }
])
</script><template><ol><!--我们给每个 todo 项提供它所表示的 todo 对象,以便能够动态展示内容。同时还需要给每个组件提供一个“key”,--><TodoItemv-for="item in groceryList":todo="item":key="item.id"></TodoItem></ol>
</template>//TodoItem.vue
<script setup>
const props = defineProps({todo: Object
})
</script><template><li>{{ todo.text }}</li>
</template>

@vue/cli脚手架

Vue CLI 里的 cli 指的是:Command Line Interface(命令行界面)
webpack自己配置环境很麻烦, 下载@vue/cli包,
@vue/cli是Vue官方提供的一个全局模块包, 用vue命令创建脚手架项目,开箱即用、0配置webpack、支持babel、css、 less、开发服务器。vue命令创建工程目录, 项目内置webpack本地热更新服务器, 帮我们打包项目预览项目

  • 安装
    把@vue/cli模块包按到全局
yarn global add @vue/cli
# OR
npm install -g @vue/clivue -V

项目里包含 webpack 吗?是的,虽然你没手动安装,但在项目的 node_modules 里,间接安装了 webpack,因为:@vue/cli-service 依赖了 webpack,你可以通过运行npm ls webpack来查看具体版本。
即使你是用 yarn 安装的 @vue/cli 或创建的项目,你依然可以用npm ls webpack来查看项目中是否安装了 webpack,因为:npm ls webpack 会去看当前项目的 node_modules 目录里是否安装了 webpack(不管你是用 npm 还是 yarn 装的)。yarn 和 npm 都是基于 package.json 和 node_modules 工作的。

  • 创建项目
    注意: 项目名不能带大写字母, 中文和特殊符号
# vue和create是命令, vuecli-demo是文件夹名
vue create vuecli-demo#选择模版preset:选择用什么方式下载脚手架项目需要的依赖包
#可以上下箭头选择, 弄错了ctrl+c重来cd vuecil-demonpm run serve 
# 或  启动本地热更新开发服务器
yarn serve
  • 文件目录
 vuecil-demo        # 项目目录├── node_modules # 项目依赖的第三方包├── public       # 静态文件目录├── favicon.ico# 浏览器小图标└── index.html # 单页面的html文件(网页浏览的是它)├── src          # 业务文件夹├── assets     # 静态资源└── logo.png # vue的logo图片├── components # 组件目录└── HelloWorld.vue # 欢迎页面vue代码文件 ├── App.vue    # 整个应用的根组件└── main.js    # webpack入口js文件├── .gitignore   # git提交忽略配置├── babel.config.js  # babel配置├── package.json  # 依赖包列表├── README.md    # 项目说明└── yarn.lock    # 项目包版本锁定和缓存地址

public/index.html – 浏览器运行的网页
src/main.js – webpack打包的入口文件 vue初始化
src/App.vue – vue项目入口页面 App.vue => main.js => index.html

  • vue项目架构
    在这里插入图片描述
  • @vue/cli 自定义配置
    项目中没有webpack.config.js文件,因为@vue/cli用的vue.config.js
    src并列处新建vue.config.js
/* 覆盖webpack的配置 */
module.exports = {devServer: { // 自定义服务配置open: true, // 自动打开浏览器port: 3000}
}
  • @vue/cli 单vue文件
    单vue文件好处, 独立作用域互不影响,不再担心变量重名问题
    Vue推荐采用.vue文件来开发项目
    template里只能有一个根标签
    vue文件-独立模块-作用域互不影响
    style配合scoped属性, 保证样式只针对当前template内标签生效
    vue文件配合webpack, 把他们打包起来插入到index.html, 然后在浏览器运行
<!--App.vue文件 -->
<!-- template必须, 只能有一个根标签, 影响渲染到页面的标签结构 -->
<template><div>欢迎使用vue</div>
</template><!-- js相关 -->
<script>
export default {name: 'App'
}
</script><!-- 当前组件的样式, 设置scoped, 可以保证样式只对当前页面有效 -->
<style scoped>
</style>

去掉默认的内容:src/App.vue默认有很多内容,以及assets 和 components 文件夹下的一切都删除掉

使用

  • 插值表达式/声明式渲染/文本插值 这三个名字是一个东西
    在dom标签中, 直接插入内容; dom中插值表达式赋值, vue的变量必须在data里声明。
    运用JSX语法 {{表达式}}
<!--App.vue文件 -->
<template><div><h1>{{ msg }}</h1><h2>{{ obj.name }}</h2><h3>{{ obj.age > 18 ? '成年' : '未成年' }}</h3></div>
</template><script>
export default {data() { // 格式固定, 定义vue数据的地方return {  // key相当于变量名msg: "hello, vue",obj: {name: "小vue",age: 5}}}
}
</script><style>
</style>
  • 写法区分
    new Vue({ data: {} }):用来创建根实例。
    export default { data() { return {} } }:用来定义一个组件。这个写法是为了让每个组件实例的数据互不干扰,所以必须写成返回对象的函数。为了组件复用时避免数据共享带来的副作用。
项目new Vue({...})export default {...}
使用位置main.js 等入口文件.vue 文件组件
作用创建整个 Vue 应用的根实例定义一个 Vue 组件
是谁调用它?你自己在写:new Vue(...)Vue 自己去加载组件用的
data写法可以直接写对象:data: {}必须是函数:data() { return {} }
组件复用性不考虑复用,数据共享没问题组件可复用,需要数据隔离
示例main.jsMyComponent.vue

vue指令

vue指令, 实质上就是特殊的 html 标签属性, 特点: v- 开头,每个指令, 都有独立的作用

  • v-bind:给dom加属性的,属性内容就是vue变量的值, 影响标签显示效果
    v-bind:属性名="vue变量"简写:属性名="vue变量"
<!-- vue指令-v-bind属性动态赋值 -->
<a v-bind:href="url">我是a标签</a>
<img :src="imgSrc">
  • v-on:给标签绑定事件
    在 Vue 中,事件修饰符给事件扩展额外功能, 可以链式书写,Vue 会从左到右依次执行修饰符
<!--
v-on:事件名="要执行的少量代码"
v-on:事件名="methods中的函数"
v-on:事件名="methods中的函数(实参)" 
无传参, 通过形参直接接收
传参, 通过$event指代事件对象传给事件处理函数
简写: @事件名="methods中的函数"
--><!--
@事件名.修饰符="methods里函数"
.stop - 阻止事件冒泡
.prevent - 阻止默认行为
.once - 程序运行期间, 只触发一次事件处理函数
--><!-- vue指令:   v-on事件绑定-->
<template><div><p>你要买商品的数量: {{count}}</p><button v-on:click="count = count + 1">增加1</button><button v-on:click="addFn">增加1个</button><button v-on:click="addCountFn(5)">一次加5件</button><button @click="subFn">减少</button><a @click="one" href="http://www.baidu.com">阻止百度</a><hr><a @click="two(10, $event)" href="http://www.baidu.com">阻止去百度</a></div>
</template>
<script>export default {// ...其他省略methods: {addFn(){ // this代表export default后面的组件对象(下属有data里return出来的属性)this.count++},addCountFn(num){this.count += num},subFn(){this.count--},one(e){e.preventDefault()},two(num, e){e.preventDefault()}}}
</script><template><div @click="fatherFn"><!-- vue对事件进行了修饰符设置, 在事件后面.修饰符名即可使用更多的功能 --><button @click.stop="btn">.stop阻止事件冒泡</button><a href="http://www.baidu.com" @click.prevent="btn">.prevent阻止默认行为</a><button @click.once="btn">.once程序运行期间, 只触发一次事件处理函数</button></div>
</template><script>
export default {methods: {fatherFn(){console.log("father被触发");},btn(){console.log(1);}}
}
</script>
  • v-on按键修饰符

给键盘事件, 添加修饰符, 增强能力

@keyup.enter  -  监测回车按键
@keyup.esc     -   监测返回按键
<template><div><input type="text" @keydown.enter="enterFn"><hr><input type="text" @keydown.esc="escFn"></div>
</template><script>
export default {methods: {enterFn(){console.log("enter回车按键了");},escFn(){console.log("esc按键了");}}
}
</script><!-- 例子 -->
<template><div><h1>{{ message }}</h1><button @click="btn">逆转世界</button></div>
</template><script>
export default {data() {return {message: "HELLO, WORLD",};},methods: {btn(){this.message = this.message.split("").reverse().join("")}}
};
</script>
  • v-model:把value属性和vue数据变量, 双向绑定到一起。
    双向数据绑定:数据变化 -> 视图自动同步,视图变化 -> 数据自动同步
v-model="vue数据变量"<template><div><!-- v-model:是实现vuejs变量和表单标签value属性, 双向绑定的指令--><div><span>用户名:</span><input type="text" v-model="username" /></div><div><span>密码:</span><input type="password" v-model="pass" /></div><div><span>来自于: </span><!-- 下拉菜单要绑定在select上 --><select v-model="from"><option value="北京市">北京</option><option value="南京市">南京</option><option value="天津市">天津</option></select></div><div><!-- (重要)遇到复选框, v-model的变量值非数组 - 关联的是复选框的checked属性数组   - 关联的是复选框的value属性--><span>爱好: </span><input type="checkbox" v-model="hobby" value="抽烟">抽烟<input type="checkbox" v-model="hobby" value="喝酒">喝酒<input type="checkbox" v-model="hobby" value="写代码">写代码</div><div><span>性别: </span><input type="radio" value="" name="sex" v-model="gender"><input type="radio" value="" name="sex" v-model="gender"></div><div><span>自我介绍</span><textarea v-model="intro"></textarea></div></div>
</template><script>
export default {data() {return {username: "",pass: "",from: "",hobby: [], sex: "",intro: "",};// 总结:// 特别注意: v-model, 在input[checkbox]的多选框状态// 变量为非数组, 则绑定的是checked的属性(true/false) - 常用于: 单个绑定使用// 变量为数组, 则绑定的是他们的value属性里的值 - 常用于: 收集勾选了哪些值}
};
</script>
  • v-model修饰符
  • v-model.修饰符=“vue数据变量”
    • .number 以parseFloat转成数字类型
    • .trim 去除首尾空白字符
    • .lazy 在change时触发而非input时
      在 Vue 中使用 v-model 时,默认是绑定在 input 事件上的,也就是说只要用户输入了内容(比如键盘敲一下),就会触发数据更新。
      lazy会改为在 change 事件时才更新绑定的数据,也就是说用户只有在失去焦点或按下 Enter 的时候,message 才会更新。
<template><div><div><span>年龄:</span><input type="text" v-model.number="age"></div><div><span>人生格言:</span><input type="text" v-model.trim="motto"></div><div><span>自我介绍:</span><textarea v-model.lazy="intro"></textarea></div></div>
</template><script>
export default {data() {return {age: "",motto: "",intro: ""}}
}
</script>
  • v-text和v-html
    注意: 会覆盖插值表达式
    v-text把值当成普通字符串显示, v-html把值当做html解析
    • v-text=“vue数据变量”
    • v-html=“vue数据变量”
<template><div><p v-text="str"></p><p v-html="str"></p></div>
</template><script>
export default {data() {return {str: "<span>我是一个span标签</span>"}}
}
</script>
  • v-show和v-if控制标签的隐藏或出现
    • v-show=“vue变量”
    • v-if=“vue变量”

原理:

  • v-show 用的display:none隐藏 (适用于:频繁切换使用)
  • v-if-else 直接从DOM树上移除
<template><div><h1 v-show="isOk">v-show的盒子</h1><h1 v-if="isOk">v-if的盒子</h1><div><p v-if="age > 18">我成年了</p><p v-else>还得多吃饭</p></div></div>
</template><script>
export default {data() {return {isOk: true,age: 15}}
}
</script><!-- 例子:折叠面板-->
<template><div id="app"><h3>案例:折叠面板</h3><div><div class="title"><h4>芙蓉楼送辛渐</h4><span class="btn" >收起</span></div><div class="container"><p>寒雨连江夜入吴,</p><p>平明送客楚山孤。</p><p>洛阳亲友如相问,</p><p>一片冰心在玉壶。</p></div></div></div>
</template><script>
export default {data() {return {}}
}
</script><style lang="less">
body {background-color: #ccc;#app {width: 400px;margin: 20px auto;background-color: #fff;border: 4px solid blueviolet;border-radius: 1em;box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);padding: 1em 2em 2em;h3 {text-align: center;}.title {display: flex;justify-content: space-between;align-items: center;border: 1px solid #ccc;padding: 0 1em;}.title h4 {line-height: 2;margin: 0;}.container {border: 1px solid #ccc;padding: 0 1em;}.btn {/* 鼠标改成手的形状 */cursor: pointer;}}
}
</style>

使用less语法,需要加载less相应模块
yarn add less@3.0.4 less-loader@5.0.0 -D

<template><div id="app"><h3>案例:折叠面板</h3><div><div class="title"><h4>芙蓉楼送辛渐</h4><span class="btn" @click="isShow = !isShow">{{ isShow ? '收起' : '展开' }}</span></div><div class="container" v-show="isShow"><p>寒雨连江夜入吴, </p><p>平明送客楚山孤。</p><p>洛阳亲友如相问,</p><p>一片冰心在玉壶。</p></div></div></div>
</template><script>
export default {data() {return {isShow: false}}
}
</script>
  • v-for
    vue最常用指令, 铺设页面利器, 快速把数据赋予到相同的dom结构上循环生成
    列表渲染, 所在标签结构, 按照数据数量, 循环生成。 目标结构:数组 / 对象 / 数字 / 字符串 (可遍历结构)
    • v-for=“(值, 索引) in 目标结构”
    • v-for=“值 in 目标结构”

注意: v-for的临时变量名不能用到v-for范围外

<template><div id="app"><div id="app"><!-- v-for 把一组数据, 渲染成一组DOM --><!-- 口诀: 让谁循环生成, v-for就写谁身上 --><p>学生姓名</p><ul><li v-for="(item, index) in arr" :key="item">{{ index }} - {{ item }}</li></ul><p>学生详细信息</p><ul><li v-for="obj in stuArr" :key="obj.id"><span>{{ obj.name }}</span><span>{{ obj.sex }}</span><span>{{ obj.hobby }}</span></li></ul><!-- v-for遍历对象(了解) --><p>老师信息</p><div v-for="(value, key) in tObj" :key="value">{{ key }} -- {{ value }}</div><!-- v-for遍历整数(了解) - 从1开始 --><p>序号</p><div v-for="i in count" :key="i">{{ i }}</div></div></div>
</template><script>
export default {data() {return {arr: ["小明", "小欢欢", "大黄"],stuArr: [{id: 1001,name: "孙悟空",sex: "男",hobby: "吃桃子",},{id: 1002,name: "猪八戒",sex: "男",hobby: "背媳妇",},],tObj: {name: "小黑",age: 18,class: "1期",},count: 10,};},
};
</script><!-- 例子 -->
<template><div id="app"><ul><li v-for="item in myArr" :key="item">{{ item }}</li></ul><button @click="btn">走一走</button></div>
</template><script>
export default {data() {return {myArr: ["帅哥", "美女", "程序猿"],};},methods: {btn() {// 头部数据加入到末尾this.myArr.push(this.myArr[0]);// 再把头部的数据删除掉this.myArr.shift();},},
};
</script><template><div id="app"><ul><li v-for="(item, ind) in arr" :key="item"><span>{{ item }}</span><button @click="del(ind)">删除</button></li></ul><button @click="add">生成</button></div>
</template><script>
export default {data() {return {arr: [1, 5, 3],};},methods: {add() {this.arr.push(Math.floor(Math.random() * 20));},del(index) {this.arr.splice(index, 1);},},
};
</script><template><div id="app"><table class="tb"><tr><th>编号</th><th>品牌名称</th><th>创立时间</th><th>操作</th></tr><!-- 循环渲染的元素tr --><tr v-for="(item,index) in list" :key="item.id"><td>{{item.id}}</td><td>{{item.name}}</td><td>{{item.time}}</td><td><button @click="del(index)">删除</button></td></tr><tr v-if="list.length === 0"><td colspan="4">没有数据咯~</td></tr></table></div>
</template><script>
export default {data() {return {list: [{ id: 1, name: "奔驰", time: "2020-08-01" },{ id: 2, name: "宝马", time: "2020-08-02" },{ id: 3, name: "奥迪", time: "2020-08-03" },],};},methods: {del(index) {// 删除按钮 - 得到索引, 删除数组里元素this.list.splice(index, 1);},},
};
</script>

v-for=“i in count” :key=“i” 里为什么“非要”加 key,其实是和 Vue 的 性能优化机制有关。推荐使用唯一的、稳定的值作为 key
在使用 v-for 渲染列表时,Vue 需要在 更新 DOM 时判断哪些元素该重用、哪些该添加、哪些该删除。加了 key,Vue 才能:更高效地更新列表(知道哪个项变了、哪个删了)、保证组件状态稳定(比如 < input> 不会错位)、减少不必要的 DOM 操作
如果你不给每个元素一个独一无二的 key,Vue 就会用一种叫 “就地复用” 的策略:简单地按顺序复用已有的 DOM 元素,不管它们代表什么数据。这有时会导致非常奇怪的行为
<input v-for="item in items" :value="item.name">如果你改变了 items 的顺序,而没设置 key,输入框的值可能会错乱,因为 DOM 元素被“错误地复用了”。

  • 为什么避免v-for和v-if在一起使用
    ​ Vue 处理指令时,v-for 比 v-if 具有更高的优先级, 虽然用起来也没报错好使, 但是性能不高, 如果你有5个元素被v-for循环, v-if也会分别执行5次.
    举例子:
<div v-for="item in items" v-if="item.visible">{{ item.name }}
</div>

这段代码 Vue 是怎么处理的?
Vue 先处理 v-for,然后才处理 v-if。
意思是:先把 items 数组的每一项都“跑一遍”(v-for),对每一项再判断一下 item.visible 是不是 true(v-if);
v-for 会让 Vue 创建 全部渲染实例(哪怕最后你只显示了其中几个),因为它不知道哪些会被 v-if 过滤掉,所以它都要先处理一遍,再做判断。
* 为什么这会影响性能?
想象一下如果 items 不是 5 个,而是 5000 个,那 Vue 就会:
先“跑一遍”5000 个元素
然后对每个元素都做 v-if 判断
虽然你最后可能只显示 10 个,但 Vue 干的活其实是 5000 次。

  • 推荐写法
    把过滤逻辑放到 computed 或 template 外面!
<template><div v-for="item in visibleItems">{{ item.name }}</div>
</template><script>
export default {computed: {visibleItems() {return this.items.filter(item => item.visible);}}
}
</script>

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

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

相关文章

【adb】bat批处理+adb 自动亮屏,自动解锁屏幕,启动王者荣耀

准备adb 下载 需要确认是否安装了adb.exe文件,可以在: 任务管理器 -->详细信息–>找一下后台运行的adb 安装过anroid模拟器,也存在adb,例如:雷电安装目录 D:\leidian\LDPlayer9 单独下载adb 官方下载地址:[官方网址] 下载目录文件: 测试adb USB连接手机 首先在设置界…

微信小程序转为App实践篇 FinClip

参考下面链接先 开始实践 微信小程序转为App并上架应用市场_微信小程序生成app-CSDN博客 首先在FinClip 官网上下载应用 小程序开发工具下载_小程序sdk下载资源-FinClip资源下载|泰坪小程序开放平台 下载到本地安装 打开导入自己的小程序项目&#xff1b;导入时会解析自己的…

arco design框架中的树形表格使用中的缓存问题

目录 1.问题 2.解决方案 1.问题 arco design框架中的树形表格使用中的缓存问题&#xff0c;使用了树形表格的load-more懒加载 点击展开按钮后&#xff0c;点击关闭&#xff0c;再次点击展开按钮时&#xff0c;没有调用查询接口&#xff0c;而是使用了缓存的数据。 2.解决方…

100个GEO基因表达芯片或转录组数据处理023.GSE24807

100个GEO基因表达芯片或转录组数据处理 写在前边 虽然现在是高通量测序的时代&#xff0c;但是GEO、ArrayExpress等数据库储存并公开大量的基因表达芯片数据&#xff0c;还是会有大量的需求去处理芯片数据&#xff0c;并且建模或验证自己所研究基因的表达情况&#xff0c;芯片…

SAP ECCS标准报表在报表中不存在特征CG细分期间 消息号 GK715报错分析

ECCS报表执行报错&#xff1a; 在报表中不存在特征CG细分期间 消息号 GK715 诊断 未在报表中指定特征CG细分期间。但是&#xff0c;同时需要特征CG细分期间和其它特征。例如&#xff1a; 期间’需要用于扩展合并组。 系统响应 处理终止 步骤 调整报表定义。 报这个错。 业务背景…

spring boot 文件下载

1.添加文件下载工具依赖 Commons IO is a library of utilities to assist with developing IO functionality. <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version> </depe…

FastAPI 中定义接口函数参数,包含请求体参数、查询参数、依赖注入参数的组合

FastAPI 中定义接口函数参数&#xff0c;包含请求体参数、查询参数、依赖注入参数的组合。 ✅ 示例结构 async def chat(request: Request,data: ChatData,conversation_id: Optional[str] Query(None),current_user: User Depends(get_current_user), ):这表示你定义了一个…

实用类题目

1. 密码强度检测 题目描述&#xff1a;生活中&#xff0c;为保证账户安全&#xff0c;密码需要有一定强度。编写一个方法&#xff0c;接收一个字符串作为密码&#xff0c;判断其是否符合以下强度要求&#xff1a;长度至少为 8 位&#xff0c;包含至少一个大写字母、一个小写字…

MATLAB学习笔记(二) 控制工程会用到的

MATLAB中 控制工程会用到的 基础传递函数表达传递函数 零极点式 状态空间表达式 相互转化画响应图线根轨迹Nyquist图和bode图现控部分求约旦判能控能观极点配置和状态观测 基础 传递函数表达 % 拉普拉斯变换 syms t s a f exp(a*t) %e的a次方 l laplace(f) …

基于YOLOv9的课堂行为检测系统

基于YOLOv9的课堂行为检测系统 项目概述 本项目是一个基于YOLOv9深度学习模型的课堂行为检测系统&#xff0c;旨在通过计算机视觉技术自动识别和监测课堂中学生的各种行为状态&#xff0c;帮助教师更好地了解课堂教学效果。 项目结构 课堂行为检测/ ├── data/ │ ├──…

C 语言中的 volatile 关键字

1、概念 volatile 是 C/C 语言中的一个类型修饰符&#xff0c;用于告知编译器&#xff1a;该变量的值可能会在程序控制流之外被意外修改&#xff08;如硬件寄存器、多线程共享变量或信号处理函数等&#xff09;&#xff0c;因此编译器不应对其进行激进的优化&#xff08;如缓存…

java 洛谷题单【算法2-1】前缀和、差分与离散化

P8218 【深进1.例1】求区间和 解题思路 前缀和数组&#xff1a; prefixSum[i] 表示数组 a 的前 (i) 项的和。通过 prefixSum[r] - prefixSum[l - 1] 可以快速计算区间 ([l, r]) 的和。 时间复杂度&#xff1a; 构建前缀和数组的时间复杂度是 (O(n))。每次查询的时间复杂度是 …

绿盟二面面试题

5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39a6eab17cc0ed0fca5f0e4c979ce64bd112762def9ee7cf0112a7e76af&scene21#wechat_redirect 1. 原理深度&…

线程安全学习

1 什么是线程 线程是cpu调度的最小单位&#xff0c;在Linux 下 实现线程的方式为轻量级进程&#xff0c;复用进程的结构体&#xff0c;使用clone函数创建 2 线程安全 所谓线程安全&#xff0c;更确切的应该描述为内存安全 #include <stdio.h> #include <pthread.h…

Linux红帽:RHCSA认证知识讲解(十 三)在serverb上破解root密码

Linux红帽&#xff1a;RHCSA认证知识讲解&#xff08;十 三&#xff09;在serverb上破解root密码 前言操作步骤 前言 在红帽 Linux 系统的管理工作中&#xff0c;系统管理员可能会遇到需要重置 root 密码的情况。本文将详细介绍如何通过救援模式进入系统并重新设置 root 密码。…

**Microsoft Certified Professional(MCP)** 认证考试

1. MCP 认证考试概述 MCP&#xff08;Microsoft Certified Professional&#xff09;是微软认证体系中的一项入门级认证&#xff0c;旨在验证考生在微软产品和技术&#xff08;如 Windows Server、Azure、SQL Server、Microsoft 365&#xff09;方面的技能。2020 年&#xff0…

系统性能优化总结与思考-第一部分

1.C代码优化策略总结 编译器方面&#xff1a;用好的编译器并用好编译器&#xff08;支持C11的编译器&#xff0c;IntelC&#xff08;速度最快&#xff09;GNU的C编译器GCC/G&#xff08;非常符合标准&#xff09;&#xff0c;Visual C&#xff08;性能折中&#xff09;&#x…

RCL谐振电压增益曲线

谐振电路如何通过调频实现稳压&#xff1f; 为什么要做谐振&#xff1f; 在谐振状态实现ZVS导通&#xff0c;小电流关断 电压增益GVo/Vin&#xff0c;相当于产出投入比 当ff0时&#xff0c;G1时&#xff0c;输出电压输入电压 当G<1时&#xff0c;输出电压<输入电压 …

Linux进程相关选择题及解析

1. 关于Linux进程创建,以下说法正确的是? A. fork()函数调用后,子进程从父进程的fork()之后开始执行 B. fork()函数返回两次,父进程返回子进程PID,子进程返回0[10][11] C. exec函数族会替换当前进程的代码段,但保留数据段和堆栈 D. wait()函数只能等待直接子进程退出 答…

STM32 HAL DHT11驱动程序

DHT11驱动程序会占用TIM3定时器&#xff0c;进行高精度延时。程序共包含4个文件 DHT11.c DHT11.h delay.c delay.h DHT11.c #include "stm32f1xx_hal.h" #include "dht11.h" #include "delay.h" // 添加延时头文件 #define DHT_PORT GPIOB…