Vue是什么?
渐进式javacript框架,一套拥有自己规则的语法。
渐进式
用什么拿什么。一开始不需要你完全掌握它的全部功能特性,可以后续逐步增加功能。没有多做职责之外的事情。
Vue虽然包含了上图中的几个组件,但我们不需要在创建项目时全部引入,每一部分都是相互独立,可以单独被使用。
库和框架
库:封装的属性或方法 (例如jQuery)。库提供了很多封装好的函数,使用灵活,哪里需要就取它里面的哪部分。
框架:提供了一整套服务,拥有自己的规则和元素, 比库强大的多 (例如Vue)。
库是方法的集合, 而框架是一套拥有自己规则的语法。
vue/cli是什么?
@vue/cli是Vue官方提供的一个全局模块包(得到vue命令),此包用于创建脚手架项目。脚手架是为了保证各施工过程顺利进行而搭设的工作平台。
脚手架好处
- 开箱即用
- 0配置webpack
- babel支持
- css, less支持
- 开发服务器支持
@vue/cli 目录和代码分析
脚手架里主要文件和作用?
- node modules-都是下载的第三方包
- public/index.html-浏览器运行的网页
- src/main.js-webpack打包的入口
- src/App.vue-Vue页面入口
- package.json-依赖包列表文件
项目入口和各文件关系是什么?
main js和App.vue, 以及index.html作用和关系?
- main.js-项目打包主入口-Vue初始化
- App.vue-Vue页面主入口
- index.html-浏览器运行的文件
- App.vue=>main.js=>index.html
脚手架项目配置文件是什么?
项目中没有webpack.config.js文件,因为Vue脚手架项目用的vue.config.js。src并列处新建vue.config.js,填入配置, 重启webpack开发服务器。
Vue基础语法
vue基础-MVVM设计模式
用数据驱动视图改变, 操作dom的事, vue源码内干了,好处是减少DOM操作, 提高开发效率。
插值表达式 {{}}
在dom标签中, 直接插入vue数据变量。双大括号,可以把vue数据变量解析显示在标签内。
前提要在data函数返回的对象上声明了变量。
Vue指令
以v-开头的标签属性,叫指令,给标签添加额外功能。以下是常用指令:
1.v-bind
2.v-on和修饰符
3.v-model和修饰符
4.v-text和v-html
5.v-show和v-if以及v-else
6.v-for
v-model
把value属性和Vue数据变量双向绑定到一起,语法: v-model="Vue数据变量"。只能用在表单元素上。
双向数据绑定:
- 变量变化 -> 视图自动同步
- 视图变化 -> 变量自动同步
原理:
v-model其实是一个语法糖,背后的本质上是包含两个操作:
- v-bind绑定一个value属性
- v-on指令给当前元素绑定input或者change事件
<template>
<div>
<input type="radio" value="男" v-model="sex" @click="test1" />
<br />
<input type="checkbox" v-model="sex2" @click="test2" />
<h1>选择是:{{ sex2 }}</h1>
</div>
</template>
<script>
export default {
data() {
return {
str: "Hello World",
sex: "",
sex2: false,
};
},
methods: {
test1(e) {
console.log(e.target.value);
},
test2(e) {}, //点击sex2的值为true
},
};
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
- text 和 textarea 元素使用 value property 和 input 事件;
- checkbox 和 radio 使用 checked property 和 change 事件;
v-model修饰符
.number 将输入的值以parseFloat转成数字类型,否则是字符串类型
.trim 去除首尾空白字符
.lazy 等表单失去焦点或者按下enter,才把值赋予给Vue数据变量
<el-form label-width="104px">
<el-form-item label="打印机型号:">
<el-select id="paddingR" size="small" clearable v-model="printForm2.modelType"
placeholder="请选择打印机" style="width: 100%;">
<el-option v-for="(item, idx) in yunModelList" :key="idx" :label="item.name"
:value="item.typeId"></el-option>
</el-select>
</el-form-item>
<el-form-item label="打印机名称:">
<el-input id="paddingR" size="small" clearable v-model.trim="printForm2.name" style="width: 100%;"
placeholder="请输入打印机名称"></el-input>
</el-form-item>
<el-form-item label="设备编号(SN):">
<el-input id="paddingR" size="small" clearable v-model.number="printForm2.deviceNo"
style="width: 100%;" placeholder="请输入设备编号(SN)">
</el-input>
</el-form-item>
<el-form-item label="备注:">
<el-input type="textarea" class="textArea" :rows="1" v-model.lazy="printForm2.remark" style="width: 100%;"
placeholder="请输入备注"></el-input>
</el-form-item>
</el-form>
v-for
循环渲染一个列表结构,常用于item in items形式的特殊语法。可以遍历数组 / 对象 / 固定数字。
值变量和索引变量不能用到v-for范围以外!!
<body>
<div id="root">
<table>
<thead>
<th>索引</th>
<th>id</th>
<th>姓名</th>
</thead>
<tbody>
<!-- v-for循环数组 -->
<tr v-for="(item,index) in list">
<td>{{index}}</td>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
<!-- v-for循环数字 -->
<div v-for="item in 10">
<span>{{item}}</span>
</div>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {
list: [
{ id: 1, name: '大头' },
{ id: 2, name: '小头' },
{ id: 3, name: '大腿' }
]
}
})
</script>
</body>
v-for更新监测
数组变更方法中改变原数组的,就会导致v-for更新、页面更新。
数组非变更方法或者直接修改值(.length=某个值 或者 下标=某个值),返回新数组,则不会导致v-for更新,如果要更新视图可以用覆盖数组或this.$set()的方法更新。
<template>
<div>
<ul>
<li v-for="item in arr" :key="item">{{ item }}</li>
</ul>
<button @click="reverse">翻转</button>
<button @click="slice">slice</button>
<button @click="update">update</button>
<h1>{{ arr }}</h1>
</div>
</template>
<script>
export default {
data() {
return {
arr: [1, 5, 33, 7, 26, 100, 62, 18],
};
},
methods: {
reverse() { //会更新页面
this.arr.reverse();
this.arr.splice(0, 1, 555);
},
slice() { //不会更新页面
this.arr.slice(0, 2);
console.log(this.arr.slice(0, 2)); //输出[1,5,33]
},
update() {
this.arr[0] = 555; //不会更新页面
this.arr.length = 5; //不会更新页面
this.$set(this.arr, 0, 555) //会更新页面
},
},
};
</script>
更新视图的数组方法:push(), pop(), shift(), unshift(), splice(), sort(), reverse()
不更新视图的数组方法:filter(), concat(), slice(), map()
更新视图方法
1、this.$set()
因为 Vue 无法探测普通的新增属性,所以用this.$set()用于向响应式对象上添加新属性,向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,才能触发视图更新 。
this.$set(object, key, value)
data(){
return{
tableData:[
{id:1, name:'小红'},
{id:2, name:'小黄'},
{id:3, name:'小黑'},
]
}
}
//不起作用
this.tableData[0] = { id:'5',name:'李白'}
console.log(this.tableData[0]) //输出 { id:'5',name:'李白'},此时对象的值更改了,但是视图没有更新
//强制更新视图
let item = { id:'5',name:'李白'}
this.$set(tableData,0,item) //对象的值变了,视图也更新了
this.set()方法是vue自带的可对数组和对象进行赋值,并触发监听的方法。(用来指向性强制刷新,性能消耗低)
参数一:你要改变的数组或对象
参数二:下标,或者元素名称
参数三:更新值
2、this.$forceUpdate()
添加this.$forceUpdate();进行强制渲染,效果可以实现。(用来全局强制刷新,性能消耗高)
调用强制更新方法this.$forceUpdate()会更新视图和数据,触发updated生命周期。
从搜索资料得出结果:因为数据层次(for循环太多)太多,render函数没有自动更新,需手动强制刷新。
// vue2的引擎这种数组下标去改变数据的时候视图不会刷新
this.arr[0]= 10000
console.log(this.arr)
// vue2知道自己的bug 全局提供给所有实例了 一个方法
// $forceUpdate() 可以让算法重新计算 刷新更新页面
this.$forceUpdate()
3、把返回的新数组,直接替换旧数组
data() {
return {
tableData: [
{id: 1, name: '小红'},
{id: 2, name: '小黄'},
{id: 3, name: '小黑'},
]
}
}
this.tableData = this.tableData.map(item => {
item.class = '三班';
return item;
});
v-for原地更新
v-for 的默认行为会尝试原地修改元素而不是移动它们。
第四个li原数组没有,要新建,新旧对比出标红的数据,更新到dom。
v-for更新时, 是如何操作DOM的?
循环出新的虚拟DOM结构, 和旧的虚拟DOM,结构对比, 尝试复用标签,原地更新内容。如果直接操作dom,会引发重拍和重绘,性能不高。
操作的原理是在内存中比较变化部分,然后给真实DOM打补丁(更新)。
真实DOM
真实DOM很多属性用不上。
虚拟DOM
它的本质是保存节点信息、属性和内容的一个JS对象。比真实DOM精简。
<template>
<div id="box">
<p class="my_p">西瓜</p>
</div>
</template>
const dom = {
type: 'div',
attributes:[{id:'box'}],
children:{
type: 'p',
attributes:[{class: 'my_p'}],
text:'西瓜'
}
}
v-bind
给元素的属性动态绑定属性值。
<body>
<div id="root">
<!-- v-bind的使用 -->
<input type="text" v-bind:placeholder="tips">
<!-- v-bind:的简写: -->
<input type="text" :placeholder="tips">
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {
tips: '请输入用户名'
},
})
</script>
</body>
v-on
事件绑定指令。
<body>
<div id="root">
<p>count的值是: {{count}}</p>
<!-- v-on的使用 -->
<button v-on:click="add">+1</button>
<!-- v-on:的简写@ -->
<button @click="add">+1</button>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {
count: 0
},
methods: {
add: function () {
console.log('ok')
}
},
})
</script>
</body>
v-on事件对象
无传参,通过形参直接接收。
传参,通过$event指代事件对象传给事件处理函数。
v-on修饰符
基本语法
@事件名.修饰符="methods里函数"
常用的修饰符
1、事件修饰符
.stop - 阻止事件冒泡
.prevent - 阻止默认行为
.once - 程序运行期间, 只触发一次事件处理函数
2、按键修饰符
@keyup.enter - 监测回车按键
@keyup.esc - 监测返回按键
v-text
将元素的文本内容设置为表达式的值,但是只会替换元素的文本内容,而不会解析其中的 HTML。
<body>
<div id="root">
<!-- 可以替换掉了标签中的内容,但会覆盖元素内部原有的内容,在实际开发中大多使用{{}}插值表达式 -->
<h1 v-text="name">{{name}}</h1>
</div>
<script type="text/javascript">
var app = new Vue({
el: '#root',
data: {
name: 'Hello World!'
}
})
</script>
</body>
v-html
v-text和插值表达式只能渲染纯文本,但v-html可以把带有标签的字符串,渲染成真正的HTML内容。
<body>
<div id="root">
<!-- v-html的使用 -->
<h1 v-html="info"></h1>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {
info:'<h3 style="color: pink; font-weigt: bold;">一起学习vue.js</h3>'
}
})
</script>
</body>
v-if / v-show
都是对元素进行显示或隐藏的指令。
区别在于:
- v-show 用的css属性display:none隐藏 。无论表达式是否为真,元素都会被渲染到 DOM 树中,只是通过 CSS 控制其可见性。所以当条件为假时,元素仍然存在于 DOM 树中。
- v-if 只有在表达式为真时才会渲染元素,并在表达式变为假时销毁元素,直接把元素从DOM树上移除。v-if 指令会触发 Vue 组件的生命周期钩子函数,如果需要恢复显示时重新加载组件用v-if更合适。
<body>
<div id="root">
<!-- v-if的使用 -->
<p v-if="flag">雪王</p>
<!-- v-show的使用 -->
<p v-show="flag">是你的雪王呢</p>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {
flag:true
},
})
</script>
</body>
v-if / v-else-if / v-else
用于条件渲染的指令,用于根据不同的条件来显示不同的内容。
v-if 当条件为真时才显示:
<div v-if="condition">
<!-- 当 condition 为真时渲染的内容 -->
</div>
v-else-if 用于在多个条件之间进行判断,并在前面的条件为假时判断当前条件是否为真。它必须紧跟在 v-if 或 v-else-if 指令之后:
<div v-if="condition1">
<!-- 当 condition1 为真时渲染的内容 -->
</div>
<div v-else-if="condition2">
<!-- 当 condition2 为真时渲染的内容 -->
</div>
v-else 在前面的条件都为假时渲染内容。它必须紧跟在 v-if 或 v-else-if 指令之后,并且不能带任何条件表达式:
<div v-if="condition1">
<!-- 当 condition1 为真时渲染的内容 -->
</div>
<div v-else>
<!-- 当 condition1 为假时渲染的内容 -->
</div>