Vue.js
一、安装Vue
1.CDN引入vue.js
2.下载引入
3.npm安装
二、Vue初体验
- mustache->体验vue响应式
编程范式:
1.声明式
2.命令式
三、创建 Vue实例
<div id="app">
{{ message }}
</div>
var app = new Vue({ //创建vue实例
el: '#app', //用户挂载要管理的元素
data: { //定义的数据
message: 'Hello Vue!'
}
})
vue实例传入的options
四、Vue的MVC
1.View 传送指令到 Controller
2.Controller 完成业务逻辑后,要求 Model 改变状态
3.Model 将新的数据发送到 View,用户得到反馈
所有通信都是单向的。
4.1Vue的MVVM
View:视图层。通常就是DOM层
ViewModel:视图模型层 。一方面实现了Data Bindiung(数据绑定),将model的改变实时的反应在View中;另一方面实现DOM Listener
( DOM监听),DOM发生的事件(点击、滚动等),可以监听到,并在需要的情况下改变对应的data
Model:数据层。数据可能是死数据,也可能是来自服务器端,从网络上请求下来的数据。
五、动态绑定class
5.1对象写法、数组写法:
<div id="app">
<div :class="{active:isActive}">{{message}}对象绑定</div>
<div :class="objClass()">{{message}}对象方法</div>
<div :class="[active,line]">{{message}}数组绑定</div>
<div :class="arrClass()">{{message}}数组绑定</div>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'dd',
isActive: true,
active:'aaa',
line:'line'
},
methods: {
objClass:function(){
return {active:this.isActive,line:this.isActive}
},
arrClass:function(){
return [this.active,this.line]
}
}
})
</script>
<style type="text/css">
.active {
color: red;
}
.line{
font-size: 30px;
}
</style>
六、动态绑定style
6.1对象写法、数组写法:
<div :style="{key(属性名):'属性值'或者data里的一个变量}">海尔</div>
<div :style="{color:'red'}">海尔</div>
<div :style="{fontSize:'20px'}">海尔</div>
七、插值语法
八、计算属性
8.1计算属性的本质
- fullname:{set,get()}
8.2计算属性和methodes对比
- 计算属性在多次使用时,只调用一次
- 它是有缓存的
8.1 计算属性会使用缓存如果多次使用,计算属性只会调用一次
<!-- 直接拼接 -->
<h2>{{firstName}}{{lastName}}</h2>
<!-- 通过定义methods -->
<!-- <div>{{fullname()}}</div> -->
<!-- 通过computed -->
<div>{{fullname}}</div>
const app = new Vue({
el: '#app',
data: {
firstName:'kobe',
lastName:'Bryant'
},
methods: {
// fullname(){
// return this.firstName+''+this.lastName
// },
},
computed:{
// filter,map,reduce
// 计算属性一般没有set方法,只读属性
fullname(){
return this.active+''+this.line
},
arrName:{
set:function(newValue){
console.log('111',newValue)
const names=newValue.split('');
console.log(names)
this.firstName=names[0];
this.lastName=names[1]
},
get:function(){
return this.firstName+''+this.lastName
}
}
}
})
九、作用域
- 在ES5之前因为if和for都没有块级作用域,所以在很多时候,我们都必须借助于function的作用域来解决应用外面变量的问题
ES5var 没有块级作用域
ES6let 有块级作用域
- 变量作用域
9.1 没有块级作用域引起的问题:if
var func;
if(true){
var name='why';
func=function(){
console.log(name);
}
func()
}
name='kobe'
func()
console.log(name)
输出结果:
作用域.html:18 why
作用域.html:18 kobe
作用域.html:24 kobe
9.2没有块级作用域引起的问题:for的块级
<div >
<button type="button">按钮1</button>
<button type="button">按钮2</button>
<button type="button">按钮3</button>
<button type="button">按钮4</button>
</div>
var btns=document.getElementsByTagName('button')
for(var i=0;i<btns.length;i++){
btns[i].addEventListener('click',function(){
// return function(){
console.log('第'+i+'个按钮');
// }
})
}
// 为什么闭包可以解决问题:函数是一个作用域
var btns=document.getElementsByTagName('button')
for(var i=0;i<btns.length;i++){
(function(i){
btns[i].addEventListener('click',function(){
// return function(){
console.log('第'+i+'个按钮');
// }
})
})(i)
}
十、 ES6
- 一旦给const修饰符的标识符被赋值之后,不能修改
- 在使用const第一标识符,必须进行赋值
- 常量的定义指的是指向的对象不能修改,但是可以改变对象内部属性的值
10.1对象的增强写法
const name='ccc'
const obj={
name,
run(){
},
eat(){
}
}
TypeScript(microsoft)->ts(类型检测)
flow->facebook)
十一、 v-on 修饰符
.stop -- 调用event.stopPropagation()
阻止冒泡.prevent --调用event.preventDefault()
阻止默认事件- 键盘修饰符.{keyCode |keyAlias}
- 自定义组件监听
<con @click.native="aonClick"></con>
- .once
- 只触发一次回调
十三、v-if和v-else的使用
<div>
<span v-if="userLogin">
<label for="user">用户登录</label>
<input type="text" name="" id="user" value="" key="user"/>
</span>
<span v-else>
<label for="email">用户邮箱</label>
<input type="text" name="" id="email" value="" key="email"/>
</span>
<button type="button" @click="userLogin=!userLogin">切换</button>
</div>
- vue在进行DOM渲染的时候,出于性能的考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素;
- 要解决不复用的我呢提可以给对应的input添加key;
13.1 v-for遍历对象和数组
<!-- 遍历对象时如果只是获取一个值 -->
<li v-for="item in info">{{item}}</li>
<!-- 获取key和value -->
<li v-for="(value,key) in info">{{value}}----{{key}}</li>
<!-- 获取key和value.index -->
<li v-for="(value,key,index) in info">{{value}}----{{key}}---{{index}}</li>
- 在列表中插入一个新的节点,diff算法默认的执行是将插入位置的值更新微新的值,按序将后面的按序更新;效率比较低
- 所以我们需要给每一个节点添加一个唯一的标识key
- Diff算法就可以正确的识别此节点
- 找到正确的位置插入新的节点
key的主要作用是为了更高效的更新虚拟DOM
- 数组可做响应式的方法
- push()方法
var arrii=['aa','a','d']
arrii.push('sss')
arrii.push('ss','ss','cc')
- pop():删除数组的最后一个元素
- shift():删除数组中的第一个元素
- unshift():在数组最前面添加元素
- splice():删除/插入/替换
第一个参数 | 插入或删除元素的开始位置 |
---|---|
第二个参数 | 1.删除元素:你要删除几个元素; 2.替换元素: 要替换几个元素,后面是用于替换前面的元素; 3.插入元素:传入0,后面跟上要插入的元素 |
第三个参数 |
- sort() :排序
- reverse():反转
(...num)
//可变参数(泛型)
vue内部的方式
set(要修改的对象,索引值,修改后的值)
Vue.set(this.arrii,0,'bbbb')
13.2 javascript中数组的高阶方法
- 购物车计算总价
const aap = new Vue({
el: '#app',
data: {
books: [{
bname: '《算法导论》',
btime: '2006-9',
bsale: 85.00,
num: 1
},
{
bname: 'UNIX编程艺术',
btime: '2006-2',
bsale: 59.00,
num: 1
},
{
bname: '《编程珠玑》',
btime: '2008-10',
bsale: 59.00,
num: 1
},
{
bname: '《代码大全》',
btime: '2006-2',
bsale: 59.00,
num: 1
},
]
},
methods: {
// 数量减
reduce(index) {
if (this.books[index].num > 0) {
this.books[index].num = this.books[index].num - 1
}
// this.
},
//数量加
add(index) {
if (this.books[index].num > 0 || this.books[index].num === 0) {
this.books[index].num = this.books[index].num + 1
}
},
//删除一个
delbook(index) {
this.books.splice(index, 1);
}
},
computed: {
total() {
var tol = 0;
// 1
// for (let i = 0; i < this.books.length; i++) {
// tol += this.books[i].num * this.books[i].bsale;
// }
// 2
// for (var i in this.books) {
// tol += this.books[i].num * this.books[i].bsale;
// }
// return tol
// 3
// for (var item of this.books) {
// tol += item.num * item.bsale;
// }
// return tol
// 4 reduce
tol=this.books.reduce(function(preValue,n){
return preValue+n.num*n.bsale
},0)
//编程思想:命令式编程,声明式编程
// 面向对象编程(第一公民:对象)/函数式编程(第一公民:函数)
//filter/map/reduce
// filter:数组中的每一个元素都会执行一次回调,回调中返回的是一个布尔值;
// 当返回false时,函数内部会过滤掉这次的n
// let newBook=this.books.filter(function(n){
// return (条件)
// })
// let newArr = this.books.map(function(n) {
// return n.bsale * 2
// })
// console.log(newArr)
// // 参数 /前一个值,当前的值
// // 重载
// tol=newArr.reduce(function(preValue,n){
// return preValue+n
// },0) //0 初始值
// let nums=[10,23,4,5,666,677];
// tol=nums.filter(function(n){
// return n<100
// }).map(function(n){
// return n*2
// }).reduce(function(preValue,n){
// return preValue+n
// },0)
// console.log(tol)
// tol=nums.filter(n=>n<100).map(n=>n*2).reduce((prev,n)=>prev+n)
return tol
}
},
filters: {
showPrice(bsale) {
return '¥' + bsale.toFixed(2)
}
}
})
十四、 v-model
1. 双向绑定
<!-- 双向绑定 -->
<input type="" name="" id="" v-model.lazy="message" />
<h2>{{typeof age}}{{age}}</h2>
<!-- 另一种实现方式 -->
<!-- <input type="" name="" id="" :value="message" @input="changeValue" /> -->
<input type="" name="" id="" :value="message" @input="message=$event.target.value" />
<h2>{{message}}</h2>
- v-model修饰符
<input type="" name="" id="" v-model.lazy="message" /> //回车时绑定值
<input type="" name="" id="" v-model.number="age" /> //number类型
<input type="" name="" id="" v-model.trim="message" />
3.radio单选框
<!-- checkbox单选框 -->
<label for="male">
<input type="radio" name="sex" id="male" value="男" v-model="sex" />男
</label>
<label for="female">
<input type="radio" name="sex" id="female" value="女" v-model="sex" />女
</label>
- checkbox多选框
<!-- checkbox多选框实现单选功能 -->
<label for="agree">
<input type="checkbox" name="" id="agree" v-model="isAgree" />是否同意
</label>
<h2>你选择的是:{{isAgree}}</h2>
<button type="button" :disabled="!isAgree">下一步</button>
一般会在同意用户隐私协议中使用
- checkbox多选情况
<label>实现多选功能</label>
<input type="checkbox" name="" id="" value="篮球" @change="valueit" />篮球
<input type="checkbox" name="" id="" value="排球" @change="valueit" />排球
<input type="checkbox" name="" id="" value="足球" @change="valueit" />足球
<input type="checkbox" name="" id="" value="乒乓球" @change="valueit" />乒乓球
const app = new Vue({
el: '#app',
data: {
message: '你好呀',
sex: '',
isAgree: false, //单选框
newArr:[], //多选框
age:3
},
methods: {
valueit(e){
this.newArr.push(e.target.value)
console.log(this.newArr)
},
changeValue(e) {
this.message = e.target.value
console.log(e.target.value)
},
},
})
- select
- input的值绑定
十五、Vue组件化开发
- 创建组件3步骤:
- Vue.extend()方法创建组件构造器
- Vue.component()方法注册组件
- 在vue的作用范围内使用组件
<div id="app">
<my-cpn></my-cpn>
</div>
//创建组件构造器对象
const cpnc=Vue.extend({
template:`<h2>sdd</h2>`
})
//注册组件
Vue.component('my-cpn',cpnc)
十六、 全局组件和局部组件
- 全局组件
Vue.component('my-cpn',cpnc)
、 - 局部组件
//创建组件构造器对象
const cpnc=Vue.extend({
template:`<h2>sdd</h2>`
})
//注册组件
// Vue.component('my-cpn',cpnc)
const app = new Vue({
el:'#app',
components:{
//使用组件时的标签名
cpn:cpnc
},
})
- 注册多个组件并使用
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
//创建组件构造器对象
const cpn1=Vue.extend({
template:`<h2>第一个组件</h2>`
})
const cpn2=Vue.extend({
template:`<h2>第二个组件</h2>`
})
//注册组件
// Vue.component('my-cpn',cpnc)
const app = new Vue({
el:'#app',
components:{
//使用组件时的标签名
cpn1:cpn1,
cpn2:cpn2
},
})
</script>
- 父子组件
<div id="app">
<!-- <cpn1></cpn1> -->
<cpn2></cpn2>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
//创建组件构造器对象
const cpn1=Vue.extend({
template:`<h2>第一个组件</h2>`
})
const cpn2=Vue.extend({
template:`<h2>第二个组件<cpn1></cpn1></h2>`, //渲染到render函数
components:{
cpn1:cpn1
}
})
//注册组件
// Vue.component('my-cpn',cpnc)
const app = new Vue({
el:'#app',
components:{
//使用组件时的标签名
// cpn1:cpn1,
cpn2:cpn2
},
})
</script>
- component注册组件语法糖
- 全局注册
Vue.component('my-cpn',{
template:`<h2>第一个组件</h2>`
})
- 局部注册
const app = new Vue({
el:'#app',
components:{
//使用组件时的标签名
'cpn3':{
template:`<h2>局部组件注册</h2>`
},
},
})
- 组件模板分离写法
组件内不能访问vue实例中的数据;
组件是一个单独功能能模块的封装:
*这个功能模块又属于自己的html模板,也该有属于自己的数据data
十七、props
两种写法
- 一、是数组写法
props:['movies','message'],
- 二、对象写法
//类型限制
props: {
cmovies: Array,
message: String
},
//提供默认值,必传值
props: {
cmovies: Array,
default: 'aaaa',
required:true
}
props: {
type: Array,
default () { //在vue2.6.11以上版本default:[]会报错,须写成函数形式
return []
}
}
十八、父子组件通信
- 父传子
<div id="app">
<cpn :cpndata="info"></cpn>
</div>
<template id="cpnn">
<h2 >{{cpndata}}</h2>
</template>
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
const cpn = {
template: '#cpnn',
props: ['cpndata']
};
const app = new Vue({
el: '#app',
data: {
info: {
name: 'ccc',
age: 20,
height: 1.80
}
},
components: {
cpn
}
})
</script>
- 子传父
<div id="app">
<cpn @itemlist="itembtn">
</cpn>
</div>
<template id="cpnn">
<h2>
<div v-for="item in infoa" @click="itemclick(item)">
{{item.name}}
</div>
</h2>
</template>
<script type="text/javascript">
const cpn = {
template: '#cpnn',
props: ['cpndata'],
data() {
return {
infoa: [{
name: 'ccc',
age: 20,
height: 1.80
},
{
name: 'abc',
age: 20,
height: 1.80
},
{
name: 'cde',
age: 20,
height: 1.80
}
]
}
},
methods: {
itemclick(item) {
this.$emit('itemlist',item)
}
}
};
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn
},
methods: {
itembtn(item){
console.log(item)
}
}
})
</script>
十九、插槽
- 基本插槽
- 具名插槽
- 作用域插槽
二十、webpack
- 导出方式
20.1webpack认识
- 本质上是一个现代的JavaScript应用的静态模块****打包工具
- 模块
进行模块化开发,处理模块之间的依赖关系 - 打包
将各种资源模块进行打包合并成一个或者多个包:包括对资源进行处理,比如压缩图片,将scss转化成css,将ES6语法转化成ES5语法,将TypeScript转化成JavaScript等
其他打包工具,grunt/gulp 适用于工程模块依赖简单,甚至石美玉用到模块化的概念,只需进行简单的合并、压缩。
20.2webpack的安装
首先安装Node.js。node.js自带软件包管理工具npm
查看你node版本 node -v
全局安装webpack npm install webpack@3.6.0 -g
vue-cli2依赖该版本
20.3webpack起步
20.4webpack的配置
webpack ./src/main.js ./dist/bundle.js //webpack打包入口文件 出口文件
20.5webpack使用
//webpack.config.js
const path=require('path')
module.exports={
entry:'./src/main.js', //入口文件
//output:'./dist/bundle.js'//出口文件
output:{
path:'动态的获取路径',//path.resolve(_dirname,'dist')
filename:'bundle.js'
}
//之后npm init 版本名字,文件名
//如果还有其他依赖 npm install
//package.js
//配置脚本
script:{
"build":"webpack"
}