Vue
前端框架 vue2.x , 使用vue 框架制作单页面应用(spa single page application)。使用虚拟 DOM 来操作页面。
搭建 vue 开发环境
- 推荐使用官方提供的vue-cli 脚手架,也可以使用 webpack 搭建(不推荐)
执行npm i @vue/cli
安装官方的脚手架工具,安装好之后可以使用vue --version
查看版本号。 - 创建开发环境
- 在你想要创建vue项目的文件夹内打开命令行工具或者在cmd页面
- 执行
vue create hello-vue
创建vue 项目,其实就是创建好了vue的开发环境 - 执行完命令之后会提示一些问题
- Please pick a preset 选择一个预设,选择vue2 的默认预设
- pick the package manager 选择一个包管理工具,选择npm(这个问题可能不会出现)
- 会根据选择下载所需要的环境
- 下载完成之后会出现 成功创建,执行提示的两条命令,运行vue 项目
- 创建好之后 就可以直接在文件夹的命令行运行
npm run serve
运行
还有一种创键方法,直接使用 vue-cli(2版本之上) 提供的 vue ui功能 直接在命令行输入vue ui
即可跳转到浏览器,在浏览器创建新项目
如何在电脑上启动或者新建一个vue 项目
- 安装 node (8.9以上) npm配置(官方源换成淘宝镜像源,显示 http 请求)
- 安装 @vue/cli 官方脚手架(要新建的话必须安装)
- 创建 vue 项目 (vue creat 项目名 或者 使用 vue ui在网页中制作) 或者安装项目的依赖 npm i
- 项目启动 ,看项目内的 package.json 文件内的script 字段,一般选择 serve 或者 start 来启动项目 。
git bash(git) vscode ps 苹果需要装 git
安装一个 谷歌 vue 工具 前端/vue-lesson/vue.crx
搭建好的 vue 项目的文件和文件夹介绍
- node_modules 文件夹 项目依赖
- pachage-lock.json 所有依赖的信息
- package.json node项目的配置文件 其中 scripts 字段简化命令 dependencies 项目必须依赖包 devDependencies 非必须依赖包
- README.md 项目介绍文件
- .gitignore 文件 作为git 仓库忽略上传的文件记录 不往 git hub上传
- public 文件夹 公共文件 是vue单页面应用的页面模板文件夹(你的 vue 项目 会以 public 下的 index.html 为模板
- ico 网页图标
- babel.config.js babel的配置文件
- src 文件夹 项目源代码(vue 代码)
- main.js 项目的入口文件(webpack 打包编译的入口文件)
- App.vue vue最外层组件(相当于 body)
- components 文件夹内放的是很多组件 相当于页面中的很多结构
- assets 文件夹 一般放图片
vue 组件
在 vue 项目开发过程中,并不需要以前的 html文件 css文件 js文件,而是以组件形式的开发模式。一个组件可以认为是页面中的任何一个结构
组件是一个.vue 后缀的文件,在整个vue 项目中,所有文件都可以被当作模块使用 es6 的模块语法进行导入导出。
vue组件的构成,组件名首字母大写 或者烤串写法
- template 标签 相当于html 结构
- 只能有一个子集
- script 标签 js
- 只能默认导出一个对象,而且这个对象内的属性和方法时vue提供的
- vue内组件做交互的话,要本着 数据变页面变的原则,所以想要控制页面的变化,先创建对应的数据,然后数据和页面绑定,最后直接修改数据,页面随之改变,注意每个组件内的数据都是独立的,不能直接操作其他组件的数据
- style 标签 css
组件的嵌套
- 在父组件中导入需要使用的子组件
- 在父组件 js 内,导出对象下写一个 components属性,该属性值是一个对象,一般属性名和子组件名相同,值是子组件本身(可简写),我们称这个 components 设置为 组件的注册
- 在 template 中,使用 组件名作为标签名, 展示对应的组件,标签一般写成 单闭合标签
组件内 数据的创建 使用 和修改
- 在组件的 script 标签内的导出对象内添加一个 data 属性, 该属性的属性值是函数,需要返回一个对象
- 在组件的 template 内如何使用数据,vue提供了模板语法
模板语法
按照数据在标签位置的不同分两种:
- 两个标签之间(插值){{变量}}
- 属性内(指令方式) v-bind可以省略成冒号
使用 v-bind 指令给属性绑定数据
<div v-bind:class="值"></div>
或<div :class="值"></div>
模板表达式内可以写 js 表达式(可以看到一个具体的值的语句)也就是说模板语法内只要最后得到一个值即可
当想要将sp: "<span>你好!</span>"
作为标签插入时,需要使用v-html="sp"
插入。
class 与 style 的绑定
就是如何将data 与 class 和 style 这两个属性进行绑定(关联)
class 的绑定 就是v-bind:class后面的值怎么写
-
对象语法
<div v-bind:class="{ box1: true, active: isActive }">
-
数组语法
<div v-bind:class="['box1', isActive ? 'active':'']"
-
数组语法中使用对象语法
<div v-bind:class="['box1', { 'active'isActive }]"
-
js 表达式 模板字符串里面放变量
<p v-bind:style="
font-size:${fontSize}px">
-
对象语法
<p v-bind:style="{fontSize:fontSize+'px'}"
-
数组语法
style 的绑定 b-bind:style
- js 表达式
事件处理
使用指令 v-on(简写成@)绑定点击事件,是在标签内直接绑定事件(类似原来的行内事件)
v-on 指令需要传递事件名作为参数 比如click mouseenter 等,值有很多种写法,
v-on的值常用的写法
- 函数 ,需要定义在导出的对象下的methods对象内,该属性的属性值是一个对象,该对象内只写方法,内部的方法就可以当作事件的事件函数,可以直接使用函数名绑定在指令上
- 当方法作为事件函数时,默认会接收一个事件作为参数,函数(普通函数)内的this,指的是当前组件,所以方法被当作事件的话不能使用箭头函数
<button @click="cli">按钮1</button>
- 当方法作为事件函数时,默认会接收一个事件作为参数,函数(普通函数)内的this,指的是当前组件,所以方法被当作事件的话不能使用箭头函数
export default {
data: () => ({
...
}),
methods: {
cli() {
this.isActive = !this.isActive;
},
},
};
- 直接写操作,但是必须和 data 相关,也就是直接修改data ,无需使用 xx.data名,直接对data进行修改
<button @click="isActive = !isActive">按钮2</button>
- 直接函数调用,改写法主要用于给事件传参,什么都不写就是什么也不传递,所以需要任何参数都要传递
- 使用
$event
向下传递事件对象
<button @click="cli()">按钮1</button>
- 使用
事件修饰符
- event.preventDefault()阻止跳转
- event.stopPropagation()阻止冒泡
<div @click="handClick1" class="box2">
<div @click.stop()="handClick2" class="box2-inner"></div>
<!-- 或者直接在@click后边+.stop() -->
</div>
methods: {
handClick1() {
console.log("我是父级");
},
handClick2(e) {
console.log("我是子级");
// e.stopPropagation();
},
},
- self 点击绑定元素本身才会触发,点内部的其他元素不会触发
- once 只触法一次
按键修饰符 其实就是当事件的时候可以使用一些案件修饰符
- .案件名
- .按键码 要不被废弃了
为什么在 HTML 中监听事件
参考官方文档
条件渲染
一般用来实现元素(标签)的添加或者删除
v-if v-else v-else-if 来实现
也可以实现css的消失和出现 v-show 值是布尔值
- v-if 值为 true 或 false,true 的时候div 显示,false的时候隐藏,不是布尔值的时候转化为布尔值
- v-else-if紧跟着跟v-if 配套使用
- v-else 紧跟着跟v-if 配套使用 v-if 为false的时候 v-else 显示
类似 if。。。else 语句
<div v-if="showNum===1">第一个</div>
<div v-else-if="showNum===2">第二个</div>
<div v-else>第三个</div>
当我们想要同事条件渲染多个元素的时候,可以将多个元素使用template 标签包裹,然后给 template 加 v-if 指令 ,为什么不直接使用div 呢,因为 template 不会渲染任何元素
Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。下面的代码中切换 loginType 将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input>
不会被替换掉——仅仅是替换了它的 placeholder
这样也不总是符合实际需求,所以 Vue 为你提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key attribute 即可
加 key 就重新渲染不加就不重新渲染
<button @click="denglu('username')">username</button>
<button @click="denglu('email')">email</button>
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username" />
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email" />
</template>
</div>
</template>
v-show 和 v-if 的区别
-
功能上 前者是 css的控制
-
后者切换开销较大,频繁切换不推荐使用,推荐使用前者
-
前者初始开销较大,不管元素出不出现,都需要渲染,当两个初始状态都是false时作比较
列表渲染
一般来实现一组相同类型的元素的渲染,使用 v-for指令实现
一般列表渲染,都是根据数组数据,在页面渲染出对应的 列表结构
指令的值写的是 vue 的循环写法 ,x in arr
,arr 表示需要循环的数组,x 表示数组内的每一项,还可以写成(x,y) in arr 和上面类似,只不过多了一个y(索引)
<ul v-if="numbers.length">
<li v-for="(num, index) in numbers" :key="num">
<span>{{ num }}</span>
<span>{{ index }}</span>
</li>
</ul>
data: () => ({
...
numbers: [1,2,3,4,5,6,7], //根据数组数量创建内容
}),
页面中生成7个li,li里面的内容放的对应的number,和索引值
使用 v-for 指令的时候,必须添加 key 属性,而且要保证每个key的值是独一无二的
给 ul 添加 v-if 搭配可以有效使用,数组有数据的时候渲染,没数据不渲染
v-for 也可以遍历对象
数据更新检测
当数据是数组的时候,在 template 中使用v-for 。此时我们修改数组,想让页面也跟着改变,修改数组的方式,但是并不是我们学过的所有方式都会引起页面的变化,也就是说有些对数组的修改操作并不会导致页面的改变
那些修改数组的操作,不能引起视图的变化
数组[index]=值
,直接修改数组的值数组.length=值
,直接修改数组长度
v-for 的循环 可以循环数组、对象、数值
可以在 template 上使用 v-for , 循环包含多个元素的内容, template 不会渲染任何标签,但是template 上不能加 key ,需要给内部所有元素加上。
在组件上使用v-for
待讲。。。。。
表单输入绑定
在vue 中,我们常用的表单,比如 输入框 input 等, vue 认为输入或者选择的时候,需要使用data控制,
当定义好了 data 的时候,表单的数据绑定,一般需要两个步骤
- 展示 data
- 提供修改 data 的事件
- 可以直接使用 v-model 指令 替代上面两个步骤
<h2>vue 中的表单</h2>
<input type="text" :value="text" @input="handInput" />
<br /><!-- 相当于 -->
<input type="text" v-model="text1" />
<br />
<label for="x">是否同意</label>
>
<input type="checkbox"id="x" :checked="isAgree" @change="isAgree = !isAgree"
/>
<br />
<!-- 相当于 -->
<label for="z">是否同意</label>
<input type="checkbox" id="z" v-model="isAgree1" />
</div>
v-model 指令修饰符 ,可以随便加
- lazy 当input使用v-model 的时候 默认的修改事件是input,输入内容数据就改变,当加了 lazy 后,变成change事件,也就是失去焦点后才改变
- number 只有输入数字才有效修改数据
- trim 自动删除左右空格
computed 计算属性
单一数据处理
侦听属性 侦听器 watch
当有些数据随着其他数据变动而变动时,而且这个改变存在异步操作,或者开销较大,计算属性就不能用了,可以考虑使用 侦听属性,但是 侦听属性是通过一个 data 的变化控制另一个 data
侦听器 watch
侦听器对象内的属性,属性名就是侦听的数据,属性值有两种,可以写成对象或函数
- 函数 当侦听的数据改变的时候 函数就触发,函数内修改对应的data
watch: {
question() {
console.log("bianhua");
},
// question: {
// handler() {
// setTimeout(() => {
// console.log("监听开始");
// this.answer = this.question.length % 2 === 1 ? "否" : "是";
// }, 500);
// },
// },
},
- 对象 对象内必须设置一个 handler 方法 ,这个方法当数据侦听改变的时候,该方法触发.除了handler 之外,还可以设置 immediate 和 deep 属性,属性值都是布尔值,默认都是 false,,immediate 设置成true ,handler 监听函数进入页面给就触发,deep 设置成 true,深度监听数据的变化
watch: {
// question() {
// console.log("bianhua");
// },
question: {
handler() {
//任何的一个方法内,最外层使用普通函数可以使用 this,嵌套的函数必须使用箭头函数才能访问 this(组件本身)
setTimeout(() => {
console.log("监听开始");
this.answer = this.question.length % 2 === 1 ? "否" : "是";
}, 500);
},
},
},
v-modle 的作用是 用户输入了 对性的 data 对应改变 当修改 data 对应的 input 也改变,当你把一个计算属性赋值给 v-modle 的时候 用户输入内容 ,就相当于对计算属性进行修改 假如有需求,要修改计算属性,那么就需要给计算属性设置 setter 去修改对应属性的 data
<div>
<label for="">firstName</label><input type="text" v-model="firstName" />
<br />
<label for="">lasttName</label><input type="text" v-model="lastName" />
<br />
<label for="">fullName</label><input type="text" v-model="fullName" />
</div>
计算属性要添加 setter 方法的话 需要写成对象类型,对象下有两个方法 get set get 方法的作用和原来的计算属性一样,就是根据 data 返回一个值 set 方法用于处理修改计算属性的,该方法会接受一个参数(value),这个参数指的是,修改后的计算属性的值
// fullName() {
// return this.firstName + " " + this.lastName;
// },
fullName: {
get() {
return this.firstName + " " + this.lastName;
},
set(value) {
this.firstName = value.split(" ")[0];
this.lastName = value.split(" ")[1];
},
},
组件的复用
- prop 主要实现的是 内容不同
如何使用- 在定义复用组件的时候,将可以变化的内容,定义成 prop。 prop 其实是需要父组件传递给子组件的,
- 在父组件中使用自组件的时候可以传递prop,其实就相当于 给标签传递属性
- 子组件中要接收父组件传递的,需要在导出的对象内添加一个props属性,属性值可以是数组或对象,数组的话,每一项就是一个父组件传递的属性,要写成属性名字符串,prop可以当作data使用
prop 接收父组件传递的参数
- 数组 [‘属性名’,‘属性名’,…]
- 对象
- 对象的属性名写成父组件传递过来的属性名,属性值写成一个对象
1. type 规定传递的prop 的值的类型
2. default 规定传递的prop 的默认值
3. required 规定是否必须传递该 prop 属性
4. validator 自定义的验证规则
<template>
<button class="btn" :style="{ backgroundColor: bgColor }">
{{ text }}
</button>
</template>
export default {
//之前写法 父组件不传递 text bgColor 就需要设置默认
// props: ["text", "bgColor"],
//新写法
props: {
text: {
type: String,
default: "默认按钮",
required: true,
//自定义一个规则,传递值的长度不能大于五,否则报错
validator(value) {
return value.length < 5;
},
},
bgColor: {
type: String,
default: "#ccc",
},
},
};
- 对象的属性名写成父组件传递过来的属性名,属性值写成值的类型
props: {
text: String,
bgColor: String,
},
当需要将对象下的所有属性一个一个的传递给子组件,可以使用 v-bind 指令简写
prop是单项的,只能父传子,而且子不能修改prop
props 的对象类型
对象下的属性名就是父组件传递的 props 名,属性值是对象,该对象下可以设置 type default required validator属性
自定义事件
类似 prop ,就是父组件想要传递一个函数给子组件,可以使用自定义事件给子组件传递函数 ,不需要prop方式
vue 推荐自定义事件名使用 kebab-case 烤串方式命名,接受的时候也是这样,因为事件名不会自动转化成驼峰
父组件:<Button text="登录(自定义事件传递)" @click="login" />
当父组件传递过来自定义事件,我们可以使用$emit接受
- 在script 内 this.$emit(‘事件名’,参数1,…)
Html:<button @click="myClick">{{text}}</button>
methods: {
myClick() {
this.$emit("click");
},
},
- 在template 内,@事件名=“ e m i t ( ′ 事 件 名 ′ , 参 数 1 , . . . . ) " 接 收 并 调 用 ‘ < b u t t o n @ c l i c k = " emit('事件名',参数1,....)"接收并调用 ` <button @click=" emit(′事件名′,参数1,....)"接收并调用‘<button@click="emit(‘click’)”>{{text}}`
自定义事件修饰符 .native 给的组件根元素绑定事件 如果根元素没有此事件 ,会没反应,可以用 $listeners 获取子组件接收到的所有事件,给子组件中的子元素绑定父元素传递过来的全部自定义事件,
.sync 修饰符(非自定义事件专用)是一个语法糖,
作用:
- 传递了prop
- 定义了一个修改数组的方法,并且将该方法当作自定义事件传递给了zi组件,该方法修改数据的方法时赋值方法。
以前当我们想要改变父组件传过来的属性值的时候,必须让父组件提供修改的方法,然后用自定义事件的方式让子组件执行,现在我们在父组件使用.sync修饰符传递变量
<SyncDemo :x.sync="number" />
然后在子组件的 template 内就使用$emit('update:变量名', 修改的值)"
可以用事件更新变量的值
<button @click="$emit('update:x', x - 1)">按钮-1</button>
.sync 同样适用于 v-bind.sync=‘对象’ ,会将对象下的所有属性都使用 sync 修饰
声明周期
每一个 vue 实例(组件) 创建的时候,都会经历一些初始化过程,其实就是执行了一些函数,所有生命周期钩子函数都可以直接写在script的导出对象(export default {})内,所有生命周期都是同步函数。
初始化:
- beforeCreate() 创建前
- created() 创建成功
组件的js相关以及模板语法都处理完毕。在这里我们可以对组件的data进行修改,通常在这里修改进入页面就要获取的数据(可以发送 ajax 请求 更新data) - beforeMount() 挂载
- mountd() 挂载成功
组件的 template 渲染渲染到页面上,那么 dom 节点渲染完毕,在这里可以获取真实 dom 节点,
指令
v- 为前缀的,叫指令,指令的值(一般为=号)可以写成js表达式,当值改变时,会响应式的影响对应的dom
指令参数:指令的冒号后面添加的,参数一般是html标签的属性
指令修饰符:参数或者指令后用 .
表示
常用指令
- v-bind 给属性绑定数据 简写 :
- v-html 往标签内插入标签
- v-on 给元素添加事件 简写 @
- v-model 给元素绑定 data 里面的变量,两个互相响应
提示
vue 项目内没有特殊情况不能使用原生dom操作
本地土拍你地址当作prop 向下传播的时候,子组件接收之后无法使用,解决方案
1.父组件传递的时候 require :src='require("本地图片地址")'
子组件接收
export default {
props: ["src", "p", "h"],
};
接受完就直接使用
- 使用 import 先导入 ,然后当作 data 使用(不推荐使用)
命名
大驼峰 FirstNameX
小驼峰 firstNameX
烤串 first-name-X