前端工程化
一:介绍:
前端工程化是使用软件工程的方法来单独办理前端的开发流程中模块化、组件化、规范化、自动化的标题,其紧张目标为了进步服从和低落本钱。
前端工程化实现技术栈
前端工程化实现的技术栈有许多,我们采用ES6+nodejs+npm+Vite+VUE3+router+pinia+axios+Element-plus组合来实现
- ECMAScript6 VUE3中大量使用ES6语法
- Nodejs 前端项目运行情况
- npm 依赖下载工具
- vite 前端项目构建工具
- VUE3 优秀的渐进式前端框架
- router 通过路由实现页面切换
- pinia 通过状态管理实现组件数据传递
- axios ajax异步哀求封装技术实现前后端数据交互
- Element-plus 可以提供丰富的快速构建网页的组件堆栈
二、ECMA6Script:
2.1.介绍:
ECMAScript 6,简称ES6,是JavaScript语言的一次重大更新。它于2015年发布,是原来的ECMAScript尺度的第六个版本。ES6带来了大量的新特性,包罗箭头函数、模板字符串、let和const关键字、解构、默认参数值、模块体系等等,大大提升了JavaScript的开发体验。由于VUE3中大量使用了ES6的语法,以是ES6成为了学习VUE3的门槛之一 。
2.2.变量与模板字符串:
变量:
- let 和var的差别
1、let 不能重复声明
2、let有块级作用域,非函数的花括号遇见let会有块级作用域,也就是只能在花括号里面访问。
3、let不会预剖析举行变量提升
4、let 界说的全局变量不会作为window的属性
5、let在es6中推荐优先使用
- const和var的差异
1、新增const和let雷同,只是const界说的变量不能修改
2、并不是变量的值不得改动,而是变量指向的那个内存地址所生存的数据不得改动。
模板字符串(template string)是增强版的字符串,用反引号(`)标识:
1、字符串中可以出现换行符
2、可以使用 ${xxx} 形式输出变量和拼接变量
- <script>
- // 1 多行普通字符串
- let ulStr =
- '<ul>'+
- '<li>JAVA</li>'+
- '<li>html</li>'+
- '<li>VUE</li>'+
- '</ul>'
- console.log(ulStr)
- // 2 多行模板字符串
- let ulStr2 = `
- <ul>
- <li>JAVA</li>
- <li>html</li>
- <li>VUE</li>
- </ul>`
- console.log(ulStr2)
- // 3 普通字符串拼接
- let name ='张小明'
- let infoStr =name+'被评为本年级优秀学员'
- console.log(infoStr)
- // 4 模板字符串拼接
- let infoStr2 =`${name}被评为本年级优秀学员`
- console.log(infoStr2)
- </script>
复制代码 2.3.解构表达式:
ES6 的解构赋值是一种方便的语法,可以快速将数组或对象中的值拆分并赋值给变量。解构赋值的语法使用花括号 {} 体现对象,方括号 [] 体现数组。通过解构赋值,函数更方便举行参数担当等。
数组解构赋值
- let [a, b, c] = [1, 2, 3]; //新增变量名任意合法即可,本质是按照顺序进行初始化变量的值
- console.log(a); // 1
- console.log(b); // 2
- console.log(c); // 3
复制代码
- 该语句将数组 [1, 2, 3] 中的第一个值赋值给 a 变量,第二个值赋值给 b 变量,第三个值赋值给 c 变量。 可以使用默认值为变量提供备选值,在数组中缺失对应位置的值时使用该默认值。比方:
- let [a, b, c, d = 4] = [1, 2, 3];
- console.log(d); // 4
复制代码 对象解构赋值
- let {a, b} = {a: 1, b: 2};
- //新增变量名必须和属性名相同,本质是初始化变量的值为对象中同名属性的值
- //等价于 let a = 对象.a let b = 对象.b
-
- console.log(a); // 1
- console.log(b); // 2
复制代码
- 该语句将对象 {a: 1, b: 2} 中的 a 属性值赋值给 a 变量,b 属性值赋值给 b 变量。 可以为标识符分配差别的变量名称,使用 : 操纵符指定新的变量名。比方:
- let {a: x, b: y} = {a: 1, b: 2};
- console.log(x); // 1
- console.log(y); // 2
复制代码 函数参数解构赋值
- function add([x, y]) {
- return x + y;
- }
- add([1, 2]); // 3
复制代码
- 该函数担当一个数组作为参数,将其中的第一个值赋给 x,第二个值赋给 y,然后返回它们的和。
- ES6 解构赋值让变量的初始化更加简朴和便捷。通过解构赋值,我们可以访问到对象中的属性,并将其赋值给对应的变量,从而进步代码的可读性和可维护性。
2.4 es6的箭头函数
ES6 答应使用“箭头” 义函数。语法雷同Java中的Lambda表达式
2.4.1 声明和特点
- <script>
-
- //ES6 允许使用“箭头”(=>)定义函数。
- //1. 函数声明
- let fn1 = function(){}
- let fn2 = ()=>{} //箭头函数,此处不需要书写function关键字
- let fn3 = x =>{} //单参数可以省略(),多参数无参数不可以!
- let fn4 = x => console.log(x) //只有一行方法体可以省略{};
- let fun5 = x => x + 1 //当函数体只有一句返回值时,可以省略花括号和 return 语句
- //2. 使用特点 箭头函数this关键字
- // 在 JavaScript 中,this 关键字通常用来引用函数所在的对象,
- // 或者在函数本身作为构造函数时,来引用新对象的实例。
- // 但是在箭头函数中,this 的含义与常规函数定义中的含义不同,
- // 并且是由箭头函数定义时的上下文来决定的,而不是由函数调用时的上下文来决定的。
- // 箭头函数没有自己的this,this指向的是外层上下文环境的this
-
- let person ={
- name:"张三",
- showName:function (){
- console.log(this) // 这里的this是person
- console.log(this.name)
- },
- viewName: () =>{
- console.log(this) // 这里的this是window
- console.log(this.name)
- }
- }
- person.showName()
- person.viewName()
-
- //this应用
- function Counter() {
- this.count = 0;
- setInterval(() => {
- // 这里的 this 是上一层作用域中的 this,即 Counter实例化对象
- this.count++;
- console.log(this.count);
- }, 1000);
- }
- let counter = new Counter();
-
- </script>
复制代码 2.4.2.使用举例:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Document</title>
- <style>
- #xdd{
- display: inline-block;
- width: 200px;
- height: 200px;
- background-color: red;
- }
- </style>
- </head>
- <body>
- <div id="xdd"></div>
- <script>
- let xdd = document.getElementById("xdd");
- // 方案1
- xdd.onclick = function(){
- console.log(this)
- let _this= this; //this 是xdd
- //开启定时器
- setTimeout(function(){
- console.log(this)
- //变粉色
- _this.style.backgroundColor = 'pink';
- },2000);
- }
- // 方案2
- xdd.onclick = function(){
- console.log(this)
- //开启定时器
- setTimeout(()=>{
- console.log(this)// 使用setTimeout() 方法所在环境时的this对象
- //变粉色
- this.style.backgroundColor = 'pink';
- },2000);
- }
- </script>
- </body>
- </html>
复制代码 对于方法一来说,setTimeout(function(){},2000);,该方法的调用者是window对象,以是直接在内部用this设置是是真的window对象的,而我们想要操纵的是xdd对象,以是我们可以用方法一的方法获取到外部的this,然后再内部使用。或者用方法二直接就用箭头函数获取到外部的this对象。
2.4.3 rest和spread
rest参数,在形参上使用 和JAVA中的可变参数几乎一样
- <script>
- // 1 参数列表中多个普通参数 普通函数和箭头函数中都支持
- let fun1 = function (a,b,c,d=10){console.log(a,b,c,d)}
- let fun2 = (a,b,c,d=10) =>{console.log(a,b,c,d)}
- fun1(1,2,3)
- fun2(1,2,3,4)
- // 2 ...作为参数列表,称之为rest参数 普通函数和箭头函数中都支持 ,因为箭头函数中无法使用arguments,rest是一种解决方案
- let fun3 = function (...args){console.log(args)}
- let fun4 = (...args) =>{console.log(args)}
- fun3(1,2,3)
- fun4(1,2,3,4)
- // rest参数在一个参数列表中的最后一个只,这也就无形之中要求一个参数列表中只能有一个rest参数
- //let fun5 = (...args,...args2) =>{} // 这里报错
- </script>
复制代码 spread参数,在实参上使用rest
- <script>
- let arr =[1,2,3]
- //let arrSpread = ...arr;// 这样不可以,...arr必须在调用方法时作为实参使用
- let fun1 =(a,b,c) =>{
- console.log(a,b,c)
- }
- // 调用方法时,对arr进行转换 转换为1,2,3
- fun1(...arr)
- //应用场景1 合并数组
- let arr2=[4,5,6]
- let arr3=[...arr,...arr2]
- console.log(arr3)
- //应用场景2 合并对象属性
- let p1={name:"张三"}
- let p2={age:10}
- let p3={gender:"boy"}
- let person ={...p1,...p2,...p3}
- console.log(person)
-
- </script>
复制代码 2.5 es6的对象创建和拷贝
2.5.1 对象创建的语法糖
ES6中新增了对象创建的语法糖,支持了class extends constructor等关键字,让ES6的语法和面向对象的语法更加靠近
- class Person{
- // 属性
- #n;
- age;
- get name(){
- return this.n;
- }
- set name(n){
- this.n =n;
- }
- // 实例方法
- eat(food){
- console.log(this.age+"岁的"+this.n+"用筷子吃"+food)
- }
- // 静态方法
- static sum(a,b){
- return a+b;
- }
- // 构造器
- constructor(name,age){
- this.n=name;
- this.age = age;
-
- }
- }
- let person =new Person("张三",10);
- // 访问对象属性
- // 调用对象方法
- console.log(person.name)
- console.log(person.n)
- person.name="小明"
- console.log(person.age)
- person.eat("火锅")
- console.log(Person.sum(1,2))
-
- class Student extends Person{
- grade ;
- score ;
- study(){
-
- }
- constructor(name,age ) {
- super(name,age);
- }
- }
-
- let stu =new Student("学生小李",18);
- stu.eat("面条")
复制代码 2.5.2 对象的深拷贝和浅拷贝
对象的拷贝,快速得到一个和已有对象相同的对象的方式
- <script>
- let arr =['java','c','python']
- let person ={
- name:'张三',
- language:arr
- }
- // 浅拷贝,person2和person指向相同的内存
- let person2 = person;
- person2.name="小黑"
- console.log(person.name)
- </script>
复制代码
- <script>
- let arr =['java','c','python']
- let person ={
- name:'张三',
- language:arr
- }
- // 深拷贝,通过JSON和字符串的转换形成一个新的对象
- let person2 = JSON.parse(JSON.stringify(person))
- person2.name="小黑"
- console.log(person.name)
- console.log(person2.name)
- </script>
复制代码 2.6 es6的模块化处理
2.6.1模块化介绍
模块化是一种构造和管理前端代码的方式,将代码拆分成小的模块单元,使得代码更易于维护、扩展和复用。它包罗了界说、导出、导入以及管理模块的方法和规范。前端模块化的紧张上风如下:
- 进步代码可维护性:通过将代码拆分为小的模块单元,使得代码结构更为清晰,可读性更高,便于开发者阅读和维护。
- 进步代码可复用性:通过将重复使用的代码变成可复用的模块,减少代码重复率,低落开发本钱。
- 进步代码可扩展性:通过模块化来实现代码的松耦合,便于更改和更换模块,从而方便地扩展功能。
> 目前,前端模块化有多种规范和实现,包罗 CommonJS、AMD 和 ES6 模块化。ES6 模块化是 JavaScript 语言的模块尺度,使用 import 和 export 关键字来实现模块的导入和导出。现在,大部分浏览器都已经原生支持 ES6 模块化,因此它成为了最为广泛使用的前端模块化尺度. `
- ES6模块化的几种暴露和导入方式
- ES6中无论以何种方式导出,导出的都是一个对象,导出的内容都可以理解为是向这个对象中添加属性或者方法
2.6.2 分别导出
- //1.分别暴露
- // 模块想对外导出,添加export关键字即可!
- // 导出一个变量
- export const PI = 3.14
- // 导出一个函数
- export function sum(a, b) {
- return a + b;
- }
- // 导出一个类
- export class Person {
- constructor(name, age) {
- this.name = name;
- this.age = age;
- }
- sayHello() {
- console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
- }
- }
复制代码
- /*
- *代表module.js中的所有成员
- m1代表所有成员所属的对象
- */
- import * as m1 from './module.js'
- // 使用暴露的属性
- console.log(m1.PI)
- // 调用暴露的方法
- let result =m1.sum(10,20)
- console.log(result)
- // 使用暴露的Person类
- let person =new m1.Person('张三',10)
- person.sayHello()
复制代码
- index.html作为步伐启动的入口 导入 app.js
- <!-- 导入JS文件 添加type='module' 属性,否则不支持ES6的模块化 -->
- <script src="./app.js" type="module" />
复制代码 2.6.3 同一导出
- //2.统一暴露
- // 模块想对外导出,export统一暴露想暴露的内容!
- // 定义一个常量
- const PI = 3.14
- // 定义一个函数
- function sum(a, b) {
- return a + b;
- }
- // 定义一个类
- class Person {
- constructor(name, age) {
- this.name = name;
- this.age = age;
- }
- sayHello() {
- console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
- }
- }
- // 统一对外导出(暴露)
- export {
- PI,
- sum,
- Person
- }
复制代码
- /*
- {}中导入要使用的来自于module.js中的成员
- {}中导入的名称要和module.js中导出的一致,也可以在此处起别名
- {}中如果定义了别名,那么在当前模块中就只能使用别名
- {}中导入成员的顺序可以不是暴露的顺序
- 一个模块中可以同时有多个import
- 多个import可以导入多个不同的模块,也可以是同一个模块
- */
- //import {PI ,Person ,sum } from './module.js'
- //import {PI as pi,Person as People,sum as add} from './module.js'
- import {PI ,Person ,sum,PI as pi,Person as People,sum as add} from './module.js'
- // 使用暴露的属性
- console.log(PI)
- console.log(pi)
- // 调用暴露的方法
- let result1 =sum(10,20)
- console.log(result1)
- let result2 =add(10,20)
- console.log(result2)
- // 使用暴露的Person类
- let person1 =new Person('张三',10)
- person1.sayHello()
- let person2 =new People('李四',11)
- person2.sayHello()
复制代码 2.6.4 默认导出
- // 3默认和混合暴露
- /*
- 默认暴露语法 export default sum
- 默认暴露相当于是在暴露的对象中增加了一个名字为default的属性
- 三种暴露方式可以在一个module中混合使用
-
- */
- export const PI = 3.14
- // 导出一个函数
- function sum(a, b) {
- return a + b;
- }
- // 导出一个类
- class Person {
- constructor(name, age) {
- this.name = name;
- this.age = age;
- }
- sayHello() {
- console.log(`Hello, my name is ${this.name}, I'm ${this.age} years old.`);
- }
- }
-
- // 导出默认
- export default sum
- // 统一导出
- export {
- Person
- }
-
复制代码
- /*
- *代表module.js中的所有成员
- m1代表所有成员所属的对象
- */
- import * as m1 from './module.js'
- import {default as add} from './module.js' // 用的少
- import add2 from './module.js' // 等效于 import {default as add2} from './module.js'
-
- // 调用暴露的方法
- let result =m1.default(10,20)
- console.log(result)
- let result2 =add(10,20)
- console.log(result2)
- let result3 =add2(10,20)
- console.log(result3)
-
- // 引入其他方式暴露的内容
- import {PI,Person} from './module.js'
- // 使用暴露的Person类
- let person =new Person('张三',10)
- person.sayHello()
- // 使用暴露的属性
- console.log(PI)
复制代码 三:Vue3:
Vue是一种流行的JavaScript框架,用于构建用户界面。它是一种渐进式框架,可以用来构建单页面应用步伐(SPA)和动态网页。Vue具有简朴易学的API,同时也提供了许多强大的功能,比方数据绑定、组件化、路由管理等。Vue的设计目标是使开发者能够更轻松地构建交互式的Web界面。
Vue3快速体验(非工程化方式):
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
- <body>
- <!-- 这里也可以用浏览器打开连接,然后将获得的文本单独保存进入一个vue.js的文件,导入vue.js文件即可 -->
- <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
- <div id="app">
- <!-- 给style属性绑定colorStyle数据 -->
- <!-- {{插值表达式 直接将数据放在该位置}} -->
- <h1 v-bind:style="colorStyle">{{headline}}</h1>
- <!-- v-text设置双标签中的文本 -->
- <p v-text="article"></p>
- <!-- 给type属性绑定inputType数据 -->
- <input v-bind:type ="inputType" value="helloVue3"> <br>
- <!-- 给按钮单击事件绑定函数 -->
- <button @click="sayHello()">hello</button>
- </div>
-
- <script>
- //组合api
- const app = Vue.createApp({
- // 在setup内部自由声明数据和方法即可!最终返回!
- setup(){
- //定义数据
- //在VUE中实现DOM的思路是: 通过修改修数据而影响页面元素
- // vue3中,数据默认不是响应式的,需要加ref或者reactive处理,后面会详细讲解
- let inputType ='text'
- let headline ='hello vue3'
- let article ='vue is awesome'
- let colorStyle ={'color':'red'}
- // 定义函数
- let sayHello =()=>{
- alert("hello Vue")
- }
- //在setup函数中,return返回的数据和函数可以在html使用
- return {
- inputType,
- headline,
- article,
- colorStyle,
- sayHello
- }
- }
- });
- //挂载到视图
- app.mount("#app");
- </script>
- </body>
- </html>
复制代码 Vite项目搭建:
1.打开VSCode,在终端输入如下信息并起名:
2.选择框架等:
3.然后就创建好了:
4.现在增长依赖,输入cd+项目名进入该项目,输入npm i增长依赖:
出现modules就成功啦。
5.输入npm run dev开始运行:
鼠标悬浮在url上面,ctrl+点击就启动了。
增补:cls清屏。
Vite+Vue3项目结构目次:

- public/ 目次:用于存放一些公共资源,如 HTML 文件、图像、字体等,这些资源会被直接复制到构建出的目标目次中。
- src/ 目次:存放项目标源代码,包罗 JavaScript、CSS、Vue 组件、图像和字体等资源。在开发过程中,这些文件会被 Vite 及时编译和处理,并在浏览器中举行及时预览和调试。以下是src内部划分发起:
- assets/ 目次:用于存放一些项目中用到的静态资源,如图片、字体、样式文件等。
- components/ 目次:用于存放组件相干的文件。组件是代码复用的一种方式,用于抽象出一个可复用的 UI 部件,方便在差别的场景中举行重复使用。
- layouts/ 目次:用于存放布局组件的文件。布局组件通常负责整个应用步伐的团体布局,如头部、底部、导航菜单等。
- pages/ 目次:用于存放页面级别的组件文件,通常是路由对应的组件文件。在这个目次下,可以创建对应的文件夹,用于存储差别的页面组件。
- plugins/ 目次:用于存放 Vite 插件相干的文件,可以按需加载差别的插件来实现差别的功能,如自动化测试、代码压缩等。
- router/ 目次:用于存放 Vue.js 的路由配置文件,负责管理视图和 URL 之间的映射关系,方便实现页面之间的跳转和数据传递。
- store/ 目次:用于存放 Vuex 状态管理相干的文件,负责管理应用步伐中的数据和状态,方便同一管理和共享数据,进步开发服从。
- utils/ 目次:用于存放一些通用的工具函数,如日期处理函数、字符串操纵函数等。
- vite.config.js 文件:Vite 的配置文件,可以通过该文件配置项目标参数、插件、打包优化等。该文件可以使用 CommonJS 或 ES6 模块的语法举行配置。
- package.json 文件:尺度的 Node.js 项目配置文件,包含了项目标基本信息和依赖关系。其中可以通过 scripts 字段界说几个下令,如 dev、build、serve 等,用于启动开发、构建和启动当地服务器等操纵。
- Vite 项目标入口为 src/main.js 文件,这是 Vue.js 应用步伐的启动文件,也是整个前端应用步伐的入口文件。在该文件中,通常会引入 Vue.js 及其相干插件和组件,同时会创建 Vue 实例,挂载到 HTML 页面上指定的 DOM 元素中。
Vite+Vue3项目组件(SFC入门)
什么是VUE的组件?
- 一个页面作为团体,是由多个部分组成的,每个部分在这里就可以理解为一个组件
- 每个.vue文件就可以理解为一个组件,多个.vue文件可以构成一个团体页面
- 组件化给我们带来的另一个好处就是组件的复用和维护非常的方便
什么是.vue文件?
- 传统的页面有.html文件.css文件和.js文件三个文件组成(多文件组件)
- vue将这文件合并成一个.vue文件(Single-File Component,简称 SFC,单文件组件)
- .vue文件对js/css/html同一封装,这是VUE中的概念 该文件由三个部分组成 <script> <template> <style>
- template标签 代表组件的html部分代码 代替传统的.html文件
- script标签 代表组件的js代码 代替传统的.js文件
- style标签 代表组件的css样式代码 代替传统的.css文件
工程化vue项目如何构造这些组件?
- index.html是项目标入口,其中 <div id ='app'></div>是用于挂载所有组建的元素
- index.html中的script标签引入了一个main.js文件,具体的挂载过程在main.js中实行
- main.js是vue工程中非常紧张的文件,他决定这项目使用哪些依赖,导入的第一个组件
- App.vue是vue中的核心组件,所有的其他组件都要通过该组件举行导入,该组件通过路由可以控制页面的切换
在打开网页的时间,展示的是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>
复制代码 其中src="/src/main.js"指向了main.js文件:
- import { createApp } from 'vue'
- import './style.css'
- import App from './App.vue'
- createApp(App).mount('#app')
复制代码 createApp(App).mount('#app')这行代码是在main.js中用来挂载一个Vue应用到指定的HTML元素上。具体来说,createApp(App)用来创建一个Vue应用实例,然后调用.mount('#app')方法将这个实例挂载到id为app的HTML元素上,从而让Vue应用在该元素中渲染和生效。
注意,它是挂载到index.html文件上面的app的。
它指向了./App.vue文件并且为它起了一个别名叫App:
- <script setup>
- import haha from "./components/haha.vue"
- </script>
- <template>
- <h1 class="h1c1">hello</h1>
- <haha></haha>
- </template>
- <style scoped>
- .h1c1{
- color:red;
- }
- </style>
复制代码 它又导入了其他的vue文件,并且使用了:
- <script setup>
- </script>
- <template>
- <h1 class="h11">haha</h1>
- </template>
- <style scoped>
- .h11{
- color:blue;
- }
- </style>
复制代码 这就是一个基本的实行次序。
CSS导入方式:
- import './style/reset.css'
- //书写引入的资源的相对路径即可!
复制代码- import './style/reset.css'
复制代码 3.Vue文件style代码引入:
- @import './style/reset.css'
复制代码 Vue相应式入门以及setup函数:
- <script type="module">
- //存储vue页面逻辑js代码
- import {ref} from 'vue'
- export default{
- setup(){
- //非响应式数据: 修改后VUE不会更新DOM
- //响应式数据: 修改后VUE会更新DOM
- //VUE2中数据默认是响应式的
- //VUE3中数据要经过ref或者reactive处理后才是响应式的
- //ref是VUE3框架提供的一个函数,需要导入
- //let counter = 1
- //ref处理的响应式数据在js编码修改的时候需要通过.value操作
- //ref响应式数据在绑定到html上时不需要.value
-
- let counter = ref(1)
- function increase(){
- // 通过.value修改响应式数据
- counter.value++
- }
- function decrease(){
- counter.value--
- }
- return {
- counter,
- increase,
- decrease
- }
- }
- }
- </script>
- <template>
- <div>
- <button @click="decrease()">-</button>
- {{ counter }}
- <button @click="increase()">+</button>
- </div>
-
- </template>
-
- <style scoped>
- button{
- border: 1px solid red;
- }
- </style>
复制代码
- 非相应式数据: 修改后VUE不会更新DOM
- 相应式数据: 修改后VUE会更新DOM
- VUE2中数据默认是相应式的
- VUE3中数据要经过ref或者reactive处理后才是相应式的
- ref是VUE3框架提供的一个函数,必要导入
- let counter = 1
- ref处理的相应式数据在js编码修改的时间必要通过.value操纵
- ref相应式数据在绑定到html上时不必要.value
语法糖:
- <script type="module" setup>
-
- /* <script type="module" setup> 通过setup关键字
- 可以省略 export default {setup(){ return{}}}这些冗余的语法结构 */
- import {ref} from 'vue'
- // 定义响应式数据
- let counter = ref(1)
- // 定义函数
- function increase(){
- counter.value++
- }
- function decrease(){
- counter.value--
- }
-
- </script>
- <template>
- <div>
- <button @click="decrease()">-</button>
- {{ counter }}
- <button @click="increase()">+</button>
- </div>
-
- </template>
-
- <style scoped>
- button{
- border: 1px solid red;
- }
- </style>
复制代码 插值表达式:
插值表达式:最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法 ,即双大括号{{}}
- 插值表达式是将数据渲染到元素的指定位置的本领之一
- 插值表达式不绝对依赖标签,其位置相对自由
- 插值表达式中支持javascript的运算表达式
- 插值表达式中也支持函数的调用
- <script setup type="module">
- let msg ="hello vue3"
- let getMsg= ()=>{
- return 'hello vue3 message'
- }
- let age = 19
- let bee = '蜜 蜂'
- // 购物车
- const carts = [{name:'可乐',price:3,number:10},{name:'薯片',price:6,number:8}];
- //计算购物车总金额
- function compute(){
- let count = 0;
- for(let index in carts){
- count += carts[index].price*carts[index].number;
- }
- return count;
- }
- </script>
-
- <template>
- <div>
- <h1>{{ msg }}</h1>
- msg的值为: {{ msg }} <br>
- getMsg返回的值为:{{ getMsg() }} <br>
- 是否成年: {{ age>=18?'true':'false' }} <br>
- 反转: {{ bee.split(' ').reverse().join('-') }} <br>
- 购物车总金额: {{ compute() }} <br/>
- 购物车总金额: {{carts[0].price*carts[0].number + carts[1].price*carts[1].number}} <br>
- </div>
- </template>
-
- <style scoped>
-
- </style>
复制代码 文本渲染:
为了渲染双标中的文本,我们也可以选择使用v-text和v-html下令
- v-*** 这种写法的方式使用的是vue的下令
- v-***的下令必须依赖元素,并且要写在元素的开始标签中
- v-***指令支持ES6中的字符串模板
- 插值表达式中支持javascript的运算表达式
- 插值表达式中也支持函数的调用
- v-text可以将数据渲染成双标签中间的文本,但是不识别html元素结构的文本
- v-html可以将数据渲染成双标签中间的文本,识别html元素结构的文本
- ```html
- <script setup type="module">
- let msg ='hello vue3'
- let getMsg= ()=>{
- return msg
- }
- let age = 19
- let bee = '蜜 蜂'
- let redMsg ='<font color=\'red\'>msg</font>'
- let greenMsg =`<font color=\'green\'>${msg}</font>`
- </script>
-
- <template>
- <div>
- <span v-text='msg'></span> <br>
- <span v-text='redMsg'></span> <br>
- <span v-text='getMsg()'></span> <br>
- <span v-text='age>18?"成年":"未成年"'></span> <br>
- <span v-text='bee.split(" ").reverse().join("-")'></span> <br>
- <span v-html='msg'></span> <br>
- <span v-html='redMsg'></span> <br>
- <span v-html='greenMsg'></span> <br>
- <span v-html="`<font color='green'>${msg}</font>`"></span> <br>
- </div>
- </template>
-
- <style scoped>
-
- </style>
复制代码 属性渲染:
想要渲染一个元素的 attribute,应该使用 v-bind指令
- 由于插值表达式不能直接放在标签的属性中,所有要渲染元素的属性就应该使用v-bind
- v-bind可以用于渲染任何元素的属性,语法为 v-bind:属性名='数据名', 可以简写为:属性名='数据名'
- <script setup type="module">
- const data = {
- name:'尚硅谷',
- url:"http://www.atguigu.com",
- logo:"http://www.atguigu.com/images/index_new/logo.png"
- }
- </script>
-
- <template>
- <div>
- <a
- v-bind:href='data.url'
- target="_self">
- <img
- :src="data.logo"
- :title="data.name">
- <br>
- <input type="button"
- :value="`点击访问${data.name}`">
- </a>
- </div>
- </template>
-
- <style scoped>
- </style>
复制代码 事件的绑定:
我们可以使用 v-on 来监听 DOM 事件,并在事件触发时实行对应的 Vue的JavaScript代码。
- 用法:v-on:click="handler" 或简写为 @click="handler"
- vue中的事件名=原生事件名去掉on 前缀 如
nClick --> click
- handler的值可以是方法事件处理器,也可以是内联事件处理器
- 绑定事件时,可以通过一些绑定的修饰符,常见的事件修饰符如下
- .once:只触发一次事件。[重点]
- .prevent:阻止默认事件。[重点]
- .stop:阻止事件冒泡。
- .capture:使用事件捕获模式而不是冒泡模式。
- .self:只在事件发送者自身触发时才触发事件。
- <script setup type="module">
- import {ref} from 'vue'
- // 响应式数据 当发生变化时,会自动更新 dom树
- let count=ref(0)
- let addCount= ()=>{
- count.value++
- }
- let incrCount= (event)=>{
- count.value++
- // 通过事件对象阻止组件的默认行为
- event.preventDefault();
-
- }
- </script>
-
- <template>
- <div>
- <h1>count的值是:{{ count }}</h1>
- <!-- 方法事件处理器 -->
- <button v-on:click="addCount()">addCount</button> <br>
- <!-- 内联事件处理器 -->
- <button @click="count++">incrCount</button> <br>
- <!-- 事件修饰符 once 只绑定事件一次 -->
- <button @click.once="count++">addOnce</button> <br>
- <!-- 事件修饰符 prevent 阻止组件的默认行为 -->
- <a href="http://www.atguigu.com" target="_blank" @click.prevent="count++">prevent</a> <br>
- <!-- 原生js方式阻止组件默认行为 (推荐) -->
- <a href="http://www.atguigu.com" target="_blank" @click="incrCount($event)">prevent</a> <br>
- </div>
- </template>
-
- <style scoped>
-
- </style>
复制代码 相应式处理:
- <script type="module" setup>
- let counter = 0;
- function show(){
- alert(counter);
- }
- </script>
-
- <template>
- <div>
- <button @click="counter--">-</button>
- {{ counter }}
- <button @click="counter++">+</button>
- <hr>
- <!-- 此案例,我们发现counter值,会改变,但是页面不改变! 默认Vue3的数据是非响应式的!-->
- <button @click="show()">显示counter值</button>
- </div>
- </template>
-
- <style scoped>
-
- </style>
复制代码 1.使用ref关键字:
- <script type="module" setup>
- /* 从vue中引入ref方法 */
- import {ref} from 'vue'
- let counter = ref(0);
- function show(){
- alert(counter.value);
- }
- /* 函数中要操作ref处理过的数据,需要通过.value形式 */
- let decr = () =>{
- counter.value--;
- }
- let incr = () =>{
- counter.value++;
- }
- </script>
-
- <template>
- <div>
- <button @click="counter--">-</button>
- <button @click="decr()">-</button>
- {{ counter }}
- <button @click="counter++">+</button>
- <button @click="incr()">+</button>
- <hr>
- <button @click="show()">显示counter值</button>
- </div>
- </template>
-
- <style scoped>
-
- </style>
复制代码 注意,在template中操纵不用加value,script要加上.value。
2.使用reaction:
- <script type="module" setup>
- /* 从vue中引入reactive方法 */
- import {ref,reactive} from 'vue'
- let data = reactive({
- counter:0
- })
- function show(){
- alert(data.counter);
- }
- /* 函数中要操作reactive处理过的数据,需要通过 对象名.属性名的方式 */
- let decr = () =>{
- data.counter--;
- }
- let incr = () =>{
- data.counter++;
- }
- </script>
-
- <template>
- <div>
- <button @click="data.counter--">-</button>
- <button @click="decr()">-</button>
- {{ data.counter }}
- <button @click="data.counter++">+</button>
- <button @click="incr()">+</button>
- <hr>
- <button @click="show()">显示counter值</button>
- </div>
- </template>
-
- <style scoped>
-
- </style>
复制代码 对比ref和reactive:
使用 ref 实用于以下开发场景:
包装基本范例数据:ref 紧张用于包装基本范例数据(如字符串、数字等),即只有一个值的数据,假如你想监听这个值的变化,用 ref 最为方便。在组件中使用时也很常见。访问方式简朴:ref 对象在访问时与平常的基本范例值没有太大区别,只必要通过 .value 访问其实际值即可。
使用 reactive 实用于以下开发场景:
包装复杂对象:reactive 可以将一个平常对象转化为相应式对象,这样在数据变化时会自动更新界面,特殊实用于处理复杂对象或者数据结构。
必要递归监听的属性:使用 reactive 可以递归追踪所有相应式对象内部的变化,从而包管界面的自动更新。
扩展相应式关键字toRefs 和 toRef:
toRef基于reactive相应式对象上的一个属性,创建一个对应的 ref相应式数据。这样创建的 ref 与其源属性保持同步:改变源属性的值将更新 ref 的值,反之亦然。toRefs将一个相应式对象多个属性转换为一个多个ref数据,这个平常对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 [toRef()]
- <script type="module" setup>
- /* 从vue中引入reactive方法 */
- import {ref,reactive,toRef,toRefs} from 'vue'
- let data = reactive({
- counter:0,
- name:"test"
- })
-
- // 将一个reactive响应式对象中的某个属性转换成一个ref响应式对象
- let ct =toRef(data,'counter');
- // 将一个reactive响应式对象中的多个属性转换成多个ref响应式对象
- let {counter,name} = toRefs(data)
-
- function show(){
- alert(data.counter);
- // 获取ref的响应对象,需要通过.value属性
- alert(counter.value);
- alert(name.value)
- }
- /* 函数中要操作ref处理过的数据,需要通过.value形式 */
- let decr = () =>{
- data.counter--;
- }
- let incr = () =>{
- /* ref响应式数据,要通过.value属性访问 */
- counter.value++;
- }
- </script>
-
- <template>
- <div>
- <button @click="data.counter--">-</button>
- <button @click="decr()">-</button>
- {{ data.counter }}
- &
- {{ ct }}
- <button @click="data.counter++">+</button>
- <button @click="incr()">+</button>
- <hr>
- <button @click="show()">显示counter值</button>
- </div>
- </template>
-
- <style scoped>
-
- </style>
-
复制代码 条件渲染:
- v-if='表达式' 只会在指令的表达式返回真值时才被渲染
- 也可以使用 v-else 为 v-if 添加一个“else 区块”。
- 一个 v-else 元素必须跟在一个 v-if 元素后面,否则它将不会被识别。
[code]<script type="module" setup>
import {ref} from 'vue'
let awesome = ref(true)
</script>
<template>
<div>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no |