2. @vue/cli脚手架
2.1@vue/cli 脚手架介绍
目标: webpack自己配置环境很麻烦, 下载@vue/cli包,用vue命令创建脚手架项目
@vue/cli是Vue官方提供的一个全局模块包(得到vue命令), 此包用于创建脚手架项目脚手架是为了保证各施工过程顺利进行而搭设的工作平台
2.2 @vue/cli 目录和代码分析
vuecil-demo # 项目目录
├── node_modules # 项目依赖的第三方包
├── public # 静态文件目录
├── favicon.ico# 浏览器小图标
└── index.html # 单页面的html文件(网页浏览的是它)
├── src # 业务文件夹
├── assets # 静态资源
└── logo.png # vue的logo图片
├── components # 组件目录
└── HelloWorld.vue # 欢迎页面vue代码文件
├── App.vue # 整个应用的根组件
└── main.js # 入口js文件
├── .gitignore # git提交忽略配置
├── babel.config.js # babel配置
├── package.json # 依赖包列表
├── README.md # 项目说明
└── yarn.lock # 项目包版本锁定和缓存地址
主要文件及含义
node_modules下都是下载的第三方包
public/index.html – 浏览器运行的网页
src/main.js – webpack打包的入口文件
src/App.vue – vue项目入口页面
package.json – 依赖包列表文件
2.3@vue/cli 项目架构了解
2.4@vue/cli 自定义配置
目标:项目中没有webpack.config.js文件,因为@vue/cli用的vue.config.js
src并列处新建vue.config.js
/* 覆盖webpack的配置 */
module.exports = {
devServer: { // 自定义服务配置
open: true, // 自动打开浏览器
port: 3000
}
}
2.5@vue/cli 单vue文件讲解
目标: 单vue文件好处, 独立作用域互不影响
Vue推荐采用.vue文件来开发项目
template里只能有一个根标签
vue文件-独立模块-作用域互不影响
style配合scoped属性, 保证样式只针对当前template内标签生效
vue文件配合webpack, 把他们打包起来插入到index.html
<!-- template必须, 只能有一个根标签, 影响渲染到页面的标签结构 -->
<template>
<div>欢迎使用vue</div>
</template>
<!-- js相关 -->
<script>
export default {
name: 'App'
}
</script>
<!-- 当前组件的样式, 设置scoped, 可以保证样式只对当前页面有效 -->
<style scoped>
</style>
最终: Vue文件配合webpack, 把他们打包起来插入到index.html, 在浏览器运行
2.6@vue/cli 欢迎界面清理
-
src/App.vue默认有很多内容, 可以全部删除留下框
-
assets 和 components 文件夹下的一切都删除掉 (不要默认的欢迎页面)
2.7 模板语法
Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。
在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统,当应用状态变更时,Vue 能够智能地推导出需要重新渲染的组件的最少数量,并应用最少的 DOM 操作。
2.8 文本插值
最基本的数据绑定形式是文本插值,使用的是“Mustache”语法 (即双大括号):
<script>
export default {
data(){
return{
msg: "模板语法"
}
}
}
</script>
<template>
<span>
Message: {{msg}}
</span>
</template>
<style scoped>
</style>
双大括号标签会被替换为相应组件实例中 msg
属性的值。同时每次 msg
属性更改时它也会同步更新。
2.9 原始 HTML
双大括号会将数据解释为纯文本,不是 HTML,若想插入HTML,用v-html指令
<script>
export default {
data(){
return{
rawHtml: "<span style="color: red">展示文本插值和html插入效果 </span>"
}
}
}
</script>
<template>
<p>这是文本插值的效果展示: {{ rawHtml }}</p>
<p>这是使用v-html的方式展示: <span style="color: red" v-html="rawHtml"></span></p>
</template>
v-html
attribute 被称为一个指令。指令由 v-
作为前缀,表明它们是一些由 Vue 提供的特殊 attribute,它们将为渲染的 DOM 应用特殊的响应式行为。这里我们做的事情就是:在当前组件实例上,将此元素的 innerHTML
与 rawHtml
属性保持同步。
3.0 v-once指令
通过v-once指令,能执行一次性的插值,当数据改变时,插值处的内容不会更新,但是这个会影响到该节点上的其他数据绑定:
示例展示:
<script>
export default {
data(){
return{
msg: "",
num: 2,
uname:""
}
}
}
</script>
<template>
<div>
<h1>{{msg}}</h1>
<h2>{{num}}</h2>
<p>{{uname}}</p>
<!--v-once 当数据改变的时候,插值处的内容不会更新-->
<p v-once>{{uname}}</p>、
<button @click="changUname">改变uname值</button>
</template>
-
如果想要改变num的值可以加一个方法调用:
-
在data方法的结尾处 ,method:{}
<script>
export default {
data(){
return{
msg: "",
num: 2,
uname:"张三"
}
},
methods:{
//给vue定义一个方法 用来改变属性值
changUname: function(){
//this 指向vue实例
this.uname="老六"
}
}
}
</script>
3. Vue指令
3.1插值表达式
在dom标签中, 直接插入内容
又叫: 声明式渲染/文本插值
语法: {{ 表达式 }}
<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>
dom中插值表达式赋值, vue的变量必须在data里声明
3.2MVVM设计模式
用数据驱动视图改变, 操作dom的事, vue源码内干了
设计模式: 是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
演示: 在上个代码基础上, 在devtool工具改变M层的变量, 观察V层(视图的自动同步)
学v-model再观察V改变M的效果
- MVVM,一种软件架构模式,决定了写代码的思想和层次
- M: model数据模型 (data里定义)
- V: view视图 (html页面)
- VM: ViewModel视图模型 (vue.js源码)- MVVM通过
数据双向绑定
让数据自动地双向同步 不再需要操作DOM
- V(修改视图) -> M(数据自动同步)
- M(修改数据) -> V(视图自动同步)
1. 在vue中,不推荐直接手动操作DOM!!!
2. 在vue中,通过数据驱动视图,不要在想着怎么操作DOM,而是想着如何操作数据!!(思想转变)
vue源码内采用MVVM设计模式思想, 大大减少了DOM操作, 挺高开发效率
3.3 v-bind
给标签属性设置vue变量的值
vue指令, 实质上就是特殊的 html 标签属性, 特点: v- 开头
每个指令, 都有独立的作用
- 语法:
v-bind:属性名="vue变量"
- 简写:
:属性名="vue变量"
<script>
import imgObj from './assets/mm.gif'
<!-- vue指令-v-bind属性动态赋值 -->
export default {
data(){
return{
url:"http://www.baidu.com",
imgUrl: "https://img13.360buyimg.com/n1/s450x450_jfs/t1/175460/22/30483/67259/638dbe8fE9900688c/83ac7462bd005fdf.jpg",
localImg: imgObj
}
}
}
</script>
<template>
<!-- 2. 值 -> 标签原生属性上 -->
<!-- 语法: v-bind:原生属性名="vue变量" -->
<a v-bind:href="url">点击去百度</a>
<!-- 语法: :原生属性名="vue变量" -->
<img :src="imgUrl" />
<img :src="localImg">
</div>
</template>
把vue变量的值, 赋予给dom属性上, 影响标签显示效果
案例2:动态更改属性的值
<script>
export default {
data(){
return{
id: "d1",
imageUrl: "https://img13.360buyimg.com/n1/s450x450_jfs/t1/175460/22/30483/67259/638dbe8fE9900688c/83ac7462bd005fdf.jpg"
}
},
methods:{
changogg:function(){
this.id="d2"
}
}
}
</script>
<template>
<div>
<!--v-bind 动态绑定属性的内容-->
<p v-bind:id="id">v-bind的绑定</p>
<img v-bind:src="imageUrl"/>
<button @click="changogg">更改id的颜色</button>
<button @click="id='d2'">更改id的颜色</button>
</div>
</template>
<style>
#d1{
color: burlywood;
}
#d2{
color: red;
}
</style>
3.4 v-on
给标签绑定事件
- 语法
- v-on:事件名=“要执行的少量代码”
- v-on:事件名=“methods中的函数”
- v-on:事件名=“methods中的函数(实参)”
- 简写: @事件名=“methods中的函数”
<!-- vue指令: v-on事件绑定-->
<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>
<script>
export default {
// ...其他省略
methods: {
addFn(){ // this代表export default后面的组件对象(下属有data里return出来的属性)
this.count++
},
addCountFn(num){
this.count += num
},
subFn(){
this.count--
}
}
}
</script>
常用@事件名, 给dom标签绑定事件, 以及=右侧事件处理函数
3.5 v-on事件对象
vue事件处理函数中, 拿到事件对象
- 语法:
- 无传参, 通过形参直接接收
- 传参, 通过 $event 指代事件对象传给事件处理函数
<template>
<div>
<a v-on: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: {
// 1. 事件触发, 无传值, 可以直接获取事件对象是
one(e){
e.preventDefault()
},
// 2. 事件触发, 传值, 需要手动传入$event
two(num, e){
e.preventDefault()
}
}
}
</script>
动态参数说明: 在指令参数中用JavaScript表达式,用方括号括起来:
示例:
<script>
export default {
data(){
return{
id: "d1",
attributeName:"id",
mouseEvent:"click",
}
}
}
</script>
<template>
<div>
<!--动态参数说明-->
<span v-bind:[attributeName]="id">v-bind的绑定</span><br>
<button @click="attributeName='class'">改变属性字体大小</button>
<!--动态事件
MouseEvent 鼠标点击事件
-->
<button @[mouseEvent]="attributeName='class'">改变属性</button>
<!--mouseover 鼠标移上事件-->
<button @click="mouseEvent='mouseover'">改变属性样式</button>
</div>
</template>
<style>
.d1{
font-size: 50px;
}
</style>
3.6 v-on修饰符
在事件后面.修饰符名 - 给事件带来更强大的功能
- 语法:
- @事件名.修饰符=“methods里函数”
- .stop - 阻止事件冒泡
- .prevent - 阻止默认行为
- .once - 程序运行期间, 只触发 一次 事件处理函数
<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>
<!--另一种写法:-->
<script>
export default {
data(){
return{
msg:"V-on 修饰符"
}
},
methods:{
fatherFn(){
console.log("father被触发 click事件")
},
oneFn(){
console.log("button标签点击了")
},
twoFn(){
console.log("button标签被点击了")
}
}
};
</script>
<template>
<div @click="fatherFn">
<h1>{{msg}}</h1>
<!-- vue对事件进行了修饰符设置, 在事件后面.修饰符名即可使用更多的功能 -->
<button @click.stop="oneFn">.stop-阻止事件冒泡</button>
<a href="http://www.baidu.com" @click.prevent="oneFn">.prevent阻止去百度</a>
<button @click.once="twoFn">点击观察事件处理函数执行几次</button>
</div>
</template>
<style>
h1{
color: red;
}
</style>
修饰符给事件扩展额外功能
3.7v-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>
3.8 翻转世界
点击按钮 - 把文字取反显示 - 再点击取反显示(回来了)
提示: 把字符串取反赋予回去
正确代码:
<template>
<div>
<!-- 1. 变量准备-静态页面铺设 -->
<h1>{{ message }}</h1>
<!-- 2. 绑定点击事件 -->
<button @click="btn">逆转世界</button>
</div>
</template>
<script>
export default {
data() {
return {
message: "HELLO, WORLD",
};
},
methods: {
btn(){
// 3.翻转字体
this.message = this.message.split("").reverse().join("")
}
}
};
</script>
分解程序:
<template>
<div>
<!-- 1. 变量准备-静态页面铺设 -->
<h1>{{message}}</h1>
<!-- 2. 绑定点击事件 -->
<button @click="btn">翻转世界</button>
</div>
</template>
<script>
export default {
data(){
return{
message:"hello,WORLD"
};
},
methods:{
btn(){
//3.截取字符串返回数组
let arr=this.message.split("")
console.log(arr)
//4.翻转
arr.reverse()
console.log(arr.reverse+"=这是什么")
//5.数组拼接起来
this.message=arr.join("")
console.log(this.message)
// 3.翻转字体
//this.message=this.message.split("").reverse().join("")
}
}
}
记住方法特点, 多做需求, vue是数据变化视图自动更新, 减少操作DOM时间, 提高开发效率
3.9 v-model
把value属性和vue数据变量, 双向绑定到一起
- 语法:
v-model=
“vue数据变量” - 双向数据绑定
- 数据变化 -> 视图自动同步
- 视图变化 -> 数据自动同步
- 演示: 用户名绑定 - vue内部是MVVM设计模式
基本使用方式:
<template>
<div>
<!--
1. v-model
双向数据绑定
value属性 - vue变量
-->
<div>
<span>用户名:</span>
<input type="text" v-model="username">
<p>{{username}}</p>
</div>
<div>
<span>密码:</span>
<input type="password" v-model="pass">
<p>{{pass}}</p>
</div>
</div>
</template>
<script>
export default {
data(){
return{
username: "",
pass:""
}
}
}
</script>
案例导入使用:
<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>
3.9.1 v-model修饰符
让v-model拥有更强大的功能
- 语法:
- v-model.修饰符=“vue数据变量”
- .number 以parseFloat转成数字类型
- .trim 去除首尾空白字符
- .lazy 在change时触发而非inupt时
<template>
<div>
<div>
<span>年龄</span>
<!-- .number修饰符-把值parseFloat转数值再赋予给v-model对应的变量 -->
<input type="text" v-model.number="age">
</div>
<div>
<!-- .trim修饰 - 去除首尾两边空格 -->
<span>人生格言</span>
<input type="text" v-model.trim="motto">
</div>
<div>
<!-- .lazy修饰符 - 失去焦点内容改变时(onchange事件), 把内容同步给v-model的变量 -->
<span>个人简介</span>
<textarea v-model.lazy="intro"></textarea>
</div>
</div>
</template>
<script>
export default {
data() {
return {
age: "",
motto: "",
intro: ""
}
}
}
</script>
v-model修饰符, 可以对值进行预处理, 非常高效好用