学习笔记|Vue的基础入门及使用

Vue的基础入门及使用 第一章 Vue核心 1.1 Vue的基本认识
1.1.1 官网

  • 英文官网:https://vuejs.org/
  • 中文官网:https://cn.vuejs.org/
1.1.2 介绍描述
  • 渐进式JavaScript框架
  • 作者:尤雨溪(一位华裔前Google工程师)
  • 作用:动态 构建用户界面
1.1.3 Vue特点
  • 1.遵循MVVM模式
    • M:Model,模型,数据对象(data)
    • V:View,视图,模板页面
    • VM:ViewModel,视图模型(Vue的实例)
  • 2.编码简洁,体积小,运行效率高,适合移动/PC端开发
  • 3.它本身只关注UI,可以轻松引入Vue插件或其他第三库开发项目
1.1.4 Vue的对象
  • el:
    • 指定dom标签容器的选择器
    • Vue就会管理对应的标签及其子标签
  • data:
    • 对象或函数类型
    • 指定初始化状态属性数据的对象
    • vm也会自动拥有data中所有属性
    • 页面中可以直接访问使用
    • 数据代理:由vm对象来代理对data中所有属性的操作(读/写)
  • methods:
    • 包含多个方法的对象
    • 供页面中的时间指令来绑定回调
    • 回调函数默认有event参数,但也可以指定自己的参数
    • 所有的方法由vue对象来调用,访问data中的属性可以直接使用this.xxx
  • computed:
    • 包含多个方法的对象
    • 对状态属性进行计算返回一个新的数据,供页面获取显示
    • 一般情况下是相当于是一个只读的属性
    • 利用set/get方法来实现属性数据的计算读取,同时监视属性数据的变化
    • 如何给对象定义get/set属性
    • 在创建对象时指定:get name(){return xxx}/set name(value) {}
    • 对象创建之后指定:Object.defineProperty(obj,age,{get(){},set(value){}})
  • watch
    • 包含多个属性监视的对象
    • 分为一般监视和深度监视
      xxx:function(value){} xxx:{ deep:true, handler:fun(value) }

    • 另一种添加监视方法:vm.$watch(‘xxx’,function(value){})
1.1.5 与其他前端JS框架的关联
  • 借鉴Angular的模板和数据绑定技术
  • 借鉴React的组件和虚拟DOM技术
1.1.6 Vue扩展插件
  • vue-cli:vue脚手架
  • vue-resouce(axios):ajax请求
  • vue-route:路由
  • vuex:状态管理
  • vue-lazyload:图片懒加载
  • vue-scoller:页面滑动相关
  • mint-ui:基于vue的UI组件库(移动端)
  • element-ui:基于vue的UI组件库(PC端)
1.2 Vue的基本使用
1.2.1 永远的HelloWorld
01_HelloWorld - 锐客网

Hello {{msg}}
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> const vm = new Vue({ // 配置对象 options // 配置选项(option) el: '#test',// element: 选择器,指定用vue来管理页面中的哪个标签区域 data: { msg: 'World' } })

1.2.2 Vue的调试工具 学习笔记|Vue的基础入门及使用
文章图片

打开Vue页面,F12进入开发者调试,选择Vue,即可使用该调试工具。
1.2.3 Vue的MVVM 学习笔记|Vue的基础入门及使用
文章图片

1.3 Vue的模板语法
1.3.1 模板的理解:
  • 动态的HTML页面
  • 包含了一些JS语法代码
  • 大括号表达式
  • 指令(以v-开头的自定义标签属性)
1.3.2 代码实现
模板语法 - 锐客网
1. 双大括号表达式 {{content}}
{{content.toUpperCase()}}
2. 指令一: 强制数据绑定 访问指定站点
访问指定站点2
访问指定站点2
3. 指令二: 绑定事件监听
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#app', data: { content: 'NBA I Love This Game', url: 'http://www.baidu.com' }, methods: { test () { alert('好啊!!!') } } })

1.4 计算属性和监视
1.4.1 计算属性
  • 在computed属性对象中定义计算属性的方法
  • 在页面中使用{{方法名}}来显示计算的结果
1.4.2 监视属性
  • 通过VM对象的$watch()或watch配置来监视指定的属性
  • 当属性变化时,回调函数自动调用,在函数内部进行计算
1.4.3 计算属性高级
  • 通过getter/setter实现对属性数据的显示和监视
  • 计算属性存在缓存,多次读取只执行一次getter计算
1.4.5 代码实现
计算属性和监视 - 锐客网
姓:
名:
姓名1(单向):
姓名2(单向):
姓名3(双向):
{{fullName1}}
{{fullName1}}
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> const vm = new Vue({ el: '#demo', data: { firstName: 'A', lastName: 'B', fullName2: 'A-B' },// 计算属性配置: 值为对象 computed: { //什么时候执行:初始化显示/相关的data属性发生变化 fullName1 () { // 属性的get() console.log('fullName1()', this) return this.firstName + '-' + this.lastName },fullName3: { // 回调函数的三个属性:1.你定义的2.你没有调用3.但是它执行了 // 回调函数:什么时候调用?用来做什么 // 当获取当前属性值时自动调用, 将返回值(根据相关的其它属性数据)作为属性值 get () { console.log('fullName3 get()') return this.firstName + '-' + this.lastName }, // 当属性值发生了改变时自动调用, 监视当前属性值变化, 同步更新相关的其它属性值 set (value) {// fullName3的最新value值A-B23 console.log('fullName3 set()', value) // 更新firstName和lastName const names = value.split('-') this.firstName = names[0] this.lastName = names[1] } } },watch: { // 配置监视firstName firstName: function (value) { // firstName发生了变化,相当于属性的set console.log('watch firstName', value) // 更新fullName2 this.fullName2 = value + '-' + this.lastName } } })// 监视lastName vm.$watch('lastName', function (value) { console.log('$watch lastName', value) // 更新fullName2 this.fullName2 = this.firstName + '-' + value })

1.5 class与style绑定
1.5.1 理解
  • 在应用界面上,某个(些)元素的样式是变化的
  • class/style绑定就是专门用来实现动态样式效果的技术
1.5.2 class绑定
  • :class=‘xxx’
  • 表达式是字符串:‘classA’
  • 表达式是对象:{classA:isA,classB:isB}
  • 表达式是数组:[‘classA’,‘classB’]
1.5.3 style绑定
  • :style="{color:activeColor,fontSize:fontSize+‘px’}"
  • 必须是对象
  • 其中activeColor/fontSize 是data属性
1.5.4 代码实现
class与style绑定 - 锐客网 > .classA { color: red; } .classB { background: blue; } .classC { font-size: 20px; }
1. class绑定: :class='xxx' xxx是字符串
xxx是对象
xxx是数组
2. style绑定 :style="{ color: activeColor, fontSize: fontSize + 'px' }"
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#demo', data: { myClass: 'classA', hasClassA: true, hasClassB: false, activeColor: 'red', fontSize: '20px' },methods: { update () { this.myClass = 'classB' this.hasClassA = !this.hasClassA this.hasClassB = !this.hasClassB this.activeColor = 'yellow' this.fontSize = '30px' } } })

1.6 条件渲染
1.6.1 条件渲染指令
  • v-if与v-else
  • v-show
1.6.2 比较v-if与v-show
  • 如果需要频繁切换,v-show较好
  • 当条件不成立时,v-if的所有子节点不会解析(项目中使用)
1.6.3 代码实现
条件渲染 - 锐客网
表白成功
表白失败
求婚成功
求婚失败
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#demo', data: { ok: true, } })

1.7 列表渲染
1.7.1 列表显示指令
  • 数组:v-for/index
  • 对象:v-for/key
1.7.2 列表的更新显示
  • 删除item
  • 替换item
1.7.3 列表的高级处理
  • 列表过滤
  • 列表排序
1.7.4 列表显示代码实现
列表渲染 - 锐客网
测试: v-for 遍历数组
  • {{index}}--{{p.name}}--{{p.age}} -- --
测试: v-for 遍历对象
  • {{key}}={{item}}
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#demo', data: { persons: [ {name: 'Tom', age:18}, {name: 'Jack', age:17}, {name: 'Bob', age:19}, {name: 'Mary', age:16} ] },methods: { deleteP (index) { this.persons.splice(index, 1) // 调用了不是原生数组的splice(), 而是一个变异(重写)方法 // 1. 调用原生的数组的对应方法 // 2. 更新界面 },updateP (index, newP) { console.log('updateP', index, newP) // this.persons[index] = newP// vue根本就不知道 this.persons.splice(index, 1, newP) // this.persons = [] },addP (newP) { this.persons.push(newP) } } })

1.7.5 列表的搜索排序
过滤与排序 - 锐客网
  • {{index}}--{{p.name}}--{{p.age}}
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#demo', data: { searchName: '', orderType: 0, // 0代表不排序, 1代表降序, 2代表升序 persons: [ {name: 'Tom', age:18}, {name: 'Jack', age:17}, {name: 'Bob', age:19}, {name: 'Mary', age:16} ] },computed: { filterPersons () { //debugger // 取出相关数据 const {searchName, persons, orderType} = this let arr = [...persons] // 过滤数组 if(searchName.trim()) { arr = persons.filter(p => p.name.indexOf(searchName)!==-1) } // 排序 if(orderType) { arr.sort(function (p1, p2) { if(orderType===1) { // 降序 return p2.age-p1.age } else { // 升序 return p1.age-p2.age }}) } return arr } },methods: { setOrderType (orderType) { this.orderType = orderType } } })

1.8 事件处理
1.8.1 绑定监听
  • v-on:xxx=“fun”
  • @xxx=“fun”
  • @xxx=“fun(参数)”
  • 默认事件形参:event
  • 隐含属性对象:$event
1.8.2 事件修饰符
  • .prevent:阻止事件的默认行为event.preventDefault()
  • .stop:停止事件冒泡 event.stopPropagation()
1.8.3 按键修饰符
  • .keycode:操作的是某个keycode值的键
  • .keyName:操作的是某个按键名的键(少部分)
1.8.4 代码实现
07_事件处理 - 锐客网
1. 绑定监听 2. 事件修饰符 百度一下
3. 按键修饰符
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#example', data: {}, methods: { test1(event) { alert(event.target.innerHTML) }, test2 (msg) { alert(msg) }, test3 (msg, event) { alert(msg+'---'+event.target.textContent) },test4 () { alert('点击了链接') },test5 () { alert('out') }, test6 () { alert('inner') },test7 (event) { console.log(event.keyCode) alert(event.target.value) } } })

1.9 表单输入绑定
1.9.1 使用v-model对表单数据自动收集
  • text/textarea 文本
  • checkbox 多选
  • radio 单选
  • select 选择
1.9.2 代码实现
表单输入绑定 - 锐客网
>用户名:
>密码:
>性别:
>爱好:
>城市: v-model="cityId">
>介绍:

type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#demo', data: { username: '', pwd: '', sex: '男', likes: ['foot'], allCitys: [{id: 1, name: 'BJ'}, {id: 2, name: 'SS'}, {id: 3, name: 'SZ'}], cityId: '2', info: '' }, methods: { handleSubmit () { console.log(this.username, this.pwd, this.sex, this.likes, this.cityId, this.info) alert('提交注册的ajax请求') } } })

1.10 Vue实例生命周期
1.10.1 生命周期流程图 学习笔记|Vue的基础入门及使用
文章图片

1.10.2 vue生命周期分析
  • 1.初始化显示
    • beforeCreate()
    • created()
    • beforeMount()
    • mounted()
  • 2.更新状态:this.xxx=value
    • beforeUpdate()
    • updated()
  • 3.销毁vue实例:vm.$destory()
    • beforeDestory()
    • destoryed()
1.10.3 常用的生命周期方法
  • created()/mounted():发送ajax请求,启动定时器等异步任务
  • beforeDestory():做收尾工作,如:清除定时器
1.10.4 代码实现
生命周期 - 锐客网
尚硅谷IT教育
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#test', data: { isShow: true },beforeCreate() { console.log('beforeCreate()') },created() { console.log('created()') },beforeMount() { console.log('beforeMount()') },mounted () { console.log('mounted()') // 执行异步任务 this.intervalId = setInterval(() => { console.log('-----') this.isShow = !this.isShow }, 1000) },beforeUpdate() { console.log('beforeUpdate()') }, updated () { console.log('updated()') },beforeDestroy() { console.log('beforeDestroy()') // 执行收尾的工作 clearInterval(this.intervalId) },destroyed() { console.log('destroyed()') },methods: { destroyVue () { this.$destroy() } } })

1.11 过渡&动画
1.11.1 vue动画的理解
  • 操作css的trasition或animation
  • vue会给目标元素添加/移除特定的class
  • 过渡的相关类名
    • xxx-enter-active:指定显示的transition
    • xxx-leave-action:指定隐藏的transition
    • xxx-enter/xxx-leave-to:指定隐藏时的样式
      学习笔记|Vue的基础入门及使用
      文章图片
1.11.2 基本过渡动画的编码
  • 在目标元素外包裹
  • 定义calss样式
    • 指定过渡样式:transition
    • 指定隐藏时的样式:opacity/其他
1.11.3 代码实现
过渡&动画 - 锐客网 > /*指定过渡样式*/ .xxx-enter-active, .xxx-leave-active { transition: opacity 1s } /*指定隐藏时的样式*/ .xxx-enter, .xxx-leave-to { opacity: 0; }.move-enter-active { transition: all 1s }.move-leave-active { transition: all 3s }.move-enter, .move-leave-to { opacity: 0; transform: translateX(20px) }
hello
hello
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#demo', data: { show: true } })new Vue({ el: '#demo2', data: { show: true } })

1.12 过滤器
1.12.1 理解过滤器
  • 功能:对要显示的数据进行特定格式化后在显示
  • 注意:并没有改变原本的数据,可以产生新的对应的数据
1.12.2 定义和使用过滤器
  • 定义过滤器
Vue.filter(filterName,function(value[,arg1,arg2,....])){ // 进行一定的数据处理 return new Value }

  • 使用过滤器
{{myData|filterName}}
{{myData|filterName(arg)}}

1.12.3 代码实现
过滤器 - 锐客网
显示格式化的日期时间 {{time}}
最完整的: {{time | dateString}}
年月日: {{time | dateString('YYYY-MM-DD')}}
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js"> > // 定义过滤器 Vue.filter('dateString', function (value, format='YYYY-MM-DD HH:mm:ss') {return moment(value).format(format); })new Vue({ el: '#test', data: { time: new Date() }, mounted () { setInterval(() => { this.time = new Date() }, 1000) } })

1.13 内置指令与自定义指令
1.13.1 常用内置指令
  • v:text:更新元素的textContent
  • v-html:更新元素的innerHTML
  • v-if:如果为true,当前标签才会输出到页面
  • v-else:如果为false,当前标签才会输出到页面
  • v-show:通过控制display样式来控制显示/隐藏
  • v-for:遍历数组/对象
  • v-on:绑定事件监听,一般简写为@
  • v-bind:强制绑定解析表达式,可以省略v-bind
  • v-model:双向数据绑定
  • ref:指定唯一标识,vue对象通过$els属性访问这个元素对象
  • v-cloak:防止闪现,与css配合:[v-cloak]{display:none}
1.13.2 自定义指令
  • 注册全局指令
Vue.directive('my-directive',function(el,binding){ el.innerHTML = binding.value.toupperCase() })

  • 注册局部指定
directives:{ 'my-directive':{ bind(el,binding){ el.innerHTML = binding.value.toupperCase() } } }

  • 使用自定义指令
v-my-directive='xxx'

1.13.5 内置编码实现
内置指令 - 锐客网 > [v-cloak] { display: none }
{{content}}


abcd
type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> new Vue({ el: '#example', data: { content: '百度一下' }, methods: { hint () { alert(this.$refs.msg.innerHTML) } } })

1.13.6 自定义指令编码实现
自定义指令 - 锐客网




type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript"> // 注册一个全局指令 // el: 指令所在的标签对象 // binding: 包含指令相关数据的容器对象 Vue.directive('upper-text', function (el, binding) { console.log(el, binding) el.textContent = binding.value.toUpperCase() }) new Vue({ el: '#test', data: { msg: "I Like You" }, // 注册局部指令 directives: { 'lower-text'(el, binding) { console.log(el, binding) el.textContent = binding.value.toLowerCase() } }})new Vue({ el: '#test2', data: { msg: "I Like You Too" } })

1.14 自定义插件
1.14.1 说明
  • Vue插件是一个包含install方法的对象
  • 通过install方法给Vue或Vue实例添加方法,定义全局指令等
1.14.2 代码实现
插件 - 锐客网

type="text/javascript" src="https://www.it610.com/js/vue.js"> type="text/javascript" src="https://www.it610.com/article/vue-myPlugin.js"> type="text/javascript"> // 声明使用插件(安装插件: 调用插件的install()) Vue.use(MyPlugin) // 内部会调用插件对象的install()const vm = new Vue({ el: '#test', data: { msg: 'HaHa' } }) Vue.myGlobalMethod() vm.$myMethod()new Object()

第二章 Vue组件化编码 2.1 使用vue-cli创建模板项目
2.1.1 说明
  • vue-cli是vue官方提供的脚手架工具
  • github:https://github.com/vuejs/vue-cli
  • 作用:从https://github.com/vuejs-templates下载模板项目
2.1.2 创建vue项目
  • npm install -g vue-cli :全局安装vue-cli
  • vue init webpack vue_demo :当前目录下创建项目名称为vue_demo的webpack模板
  • cd vue_demo :进入vue_demo文件夹
  • npm install :安装
  • npm run serve :运行该项目
  • 访问http://localhost:8080 :项目访问地址
2.1.3 项目结构
  • build:webpack相关的配置文件夹(基本上不需要修改)
    • dev-serve.js:通过express启动后台服务器
  • config:webpack相关的配置文件夹(基本上不需要修改)
    • index.js:指定的后台服务的端口号和静态资源文件夹
  • node_modules:vue的依赖
  • src:源码文件夹
    • components:vue组件及其相关资源文件夹
    • App.vue:应用根主组件
    • main.js:应用入口js
  • static:静态资源文件夹
  • .babelrc:babel的配置文件
  • .selintignore:eslint检查忽略的配置
  • .eslintrc.js:eslint检查的配置
  • .gitignore:git版本管制忽略的配置
  • index.html:主页面的文件
  • package.json:应用包配置文件
  • README.md:应用描述说明的readme文件
2.2 项目的打包与发布
2.2.1 打包
  • npm run build
2.2.2 发布1:使用静态服务器工具包(nginx等—)
  • npm install -g serve
  • serve dist
  • 访问:http://localhost:5000
2.2.3 发布2:使用动态web服务器(tomcat)
  • 修改配置:webpack.prod.conf.js
output:{ publicPath:'/xxx/'//打包文件夹的名称 }

  • 重新打包
    • npm run build
  • 修改dist文件夹为项目名称:xxx
  • 将xxx拷贝到运行的tomcat的webapps目录下
  • 访问:http://localhost:8080/xxx
2.3 eslint
2.3.1 说明
  • ESLint是一个代码规范检查工具
  • 它定义了很多特定的规则,一旦你的代码违背了某一规则,eslint会作出非常有用的提示
  • 官网:http://eslint.org/
  • 基本已经替代以前的JSLint
2.3.2 ESLint提供以下支持
  • ES
  • JSX
  • style检查
  • 自定义错误和提示
2.3.3 ESLint提供以下几种校验
  • 语法错误校验
  • 不重要或丢失的标点符号,如分号
  • 没法运行到的代码块
  • 未被使用的参数提醒
  • 确保样式的统一规则,如sass或者less
  • 检查变量的命名
2.3.4 规则的错误等级有三种
  • 0:关闭规则
  • 1:打开规则,并且作为一个警告(信息打印黄色字体)
  • 2:打开规则,并且作为一个错误(信息打印红色字体)
2.3.5 相关配置文件
  • .eslintrc.js:全局规则配置文件
'rules':{ 'no-new':1 }

  • 在js/vue文件中修改局部规则
/* eslint-disable no-new*/ new Vue({ el:'#body', components:{App} })

  • .eslintignore:指令检查忽略的文件
*.js *.vue

2.4 组件定义与使用
2.4.1 vue文件的组成(3个部分)
  • 模板页面

  • JS模块对象
> export default{ data(){//模板里面只能写方法 return:{} }, methods:{}, computed:{}. components:{} }

  • 样式
> 样式定义

2.4.2 基本使用
  • 引入组件
  • 映射成标签
  • 使用组件标签
> //1.引入组件 import HelloWorld from './components/HelloWorld.vue' export default { // 2.映射组件标签 components:{ HelloWorld } } >

2.4.3 关于标签名与标签属性名书写问题
  • 写法一:一模一样
  • 写法二:大写变小写,并用-连接
2.5 组件间通信
2.5.1 组件间通信基本原则
  • 不要在子组件中直接修改父组件的状态数据
  • 数据在哪,更新数据的行为(函数)就应该定义在哪
2.5.2 vue组件间通信方式
  • props
  • vue的自定义事件
  • 消息订阅与发布(如:pubsub库)
  • slot
  • vuex(后面单独)
2.6 组件间通信1:props
2.6.1 使用组件标签

2.6.2 定义MyComponent时
  • 在组件内声明所有的props
  • 方式一:只指定名称
props:['name','age','setName']

  • 方式二:指定名称和类型
props:{ name:String, age:Number, setName:Function }

  • 方式三:指定名称/类型/必要性/默认值
props:{ name:{type:String,required:true,default:xxx} }

2.6.3 注意
  • 此方式用于父组件向子组件传递数据
  • 所有标签属性都会成为组件对象的属性,模板页面可以直接引用
  • 问题:
    • 如果需要向非子后代传递数据,必须多层逐层传递
    • 兄弟组件间也不能直接pops通信,必须借助父组件才可以
2.7 组件间通信2:vue自定义事件
2.7.1 绑定事件监听
//方式一:通过v-on绑定 @delete_to="deleteTodo" //方式二:通过$on() this.$refs.xxx.$on('delete_todo',function(todo)){ this.deleteTodo(todo) }

2.7.2 触发事件
//触发事件 this.$emit(eventName,data)

2.7.3 注意
  • 此方式只适用于子组件向父组件发送消息(数据)
  • 问题:隔代组件或兄弟组件间通信此种方式不合适
2.8 组件间通信3:消息订阅与发布
2.8.1 订阅消息
PubSub.subscribt('msg',function(msg,data){})

2.8.2 发布新消息
PubSub.publish('msg',data)

2.8.3 注意 优点:此方式可实现任意关系组件间的通信(数据)
2.8.4 事件的两个重要操作
  • 绑定事件监听(订阅消息)
    • 目标:标签元素
    • 事件名(类型):click/focus
    • 回调函数:function(event){}
  • 触发事件(发布消息)
    • DOM事件:用户在浏览器上对应的界面上做对应的操作
    • 自定义:编码手动触发
2.9 组件间通信4:slot
2.9.1 理解 此方式用于父组件向子组件传递“标签数据”
2.9.2 子组件:Child.vue

2.9.3 父组件:Parent.vue
xxx对应的标签结构
yyy对应的标签结构

第三章 Vue-Ajax 3.1 Vue项目中常用的2个ajax库
3.1.1 Vue-Resource vue插件,非官方库,vue1.x使用广泛
3.1.2 axios 通用的Ajax请求库,官方推荐,vue2.x使用广泛
3.2 Vue-Resource的使用
3.2.1 在线文档 https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
3.2.2 下载 npm install vue-resource --save
3.2.3 代码使用
// 引入模块 import VueResource from 'vue-resource' // 使用插件 Vue.use(VueResource)// 通过vue组件对象发送ajax请求 this.$http.get('/someURL').then(response)=>{ //请求成功的数据 console.log(response.data)//返回结果数据 },(response)=>{ //错误信息 console.log(response.statusText)//错误信息 }

3.3 axios的使用
3.3.1 下载 npm install axios --save
3.3.2 代码实现
// 引入模块 import axios from 'axios'//发送Ajax请求 axios.get(url).then(response=>{ console.log(response.data)//得到返回结果数据 }).catch(error=>{ console.log(error.message)//错误信息 })

第四章 Vue UI组件库 4.1 常用的UI组件库
  • Mint UI:
    • 饿了么开源的基于vue的移动端UI组件库
  • Elment UI:
    • 饿了么开源的基于vue的PC端UI组件库
4.2 使用Mint UI
4.2.1 下载 npm install --save mint-ui
4.2.2 实现按需打包
// 下载 npm install --save-dev babel-plugin-component // 修改babel配置 "plugins":["transform-runtime",["component",{ "libraryName":"mint-ui", "style":true }]]

4.2.3 mint-ui组件分类
  • 标签组件
  • 非标签组件
4.2.4 使用mint-ui
  • index.html
src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"> > if('addEventListener' in document){ document.addEventListener('DOMContentLoaded',function(){ FastClick.attach(document.body); },false); } if(!window.Promise){ document.writelv('="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js">') }

  • main.js
import {Button} from 'mint-ui' Vue.component(Button.name,Button)

  • App.vue
> import {Toast} from 'mint-ui' export default{ methods:{ handleClick(){ Toast('点击了测试'); } } }

第五章 Vue-router 5.1 理解
5.1.1 说明
  • 官方提供的用来实现SPA(单页)的vue插件
  • github:https://github.com/vuejs/vue-router
  • 中文文档:http://router.vuejs.org/zh-cn/
  • 下载:npm install vue-router --save
5.1.2 相关API说明
  • VueRouter():用于创建路由器的构建函数
new VueRouter({ //多个配置项 })

  • 路由配置
routes:[ {//一般路由 path:'/about', component:About }, {//自动跳转路由 path:'/', redirect:'/about' } ]

  • 注册路由器
import router from './router' new Vue({ router })

  • 使用路由组件标签
1.:用来生成路由链接 Go To XXX 2.:用来显示当前路由组件界面

5.2 基本路由
5.2.1 路由组件 文件夹命名:pages/views
示例路由组件:Home.vue/About.vue
5.2.2 应用组件:App.vue
About

5.2.3 路由器模块:src/router/index.js
export default new VueRouter({ routes:[ { path:'/', redirect:'/about' }, { path:'/about', component:About }, { path:'/home', component:Home } ] })

5.2.4 注册路由器:main.js
import Vue from 'vue' import router from './router' // 创建vue配置路由器 new Vue({ el:'#app', router, render:h=>h(app) })

5.2.5 优化路由器配置 linkActiveClass:‘active’; //指定选中的路由链接的class
5.2.6 总结:编写使用路由的3步
  • 定义路由组件
  • 注册路由
  • 使用路由
5.3.1 子路由组件 News.vue
Message.vue
5.3.2 配置嵌套路由:router.js
path:'/home', component:hoem, children:[ { path:'/home/news', component:News }, { path:'message',//简化写法 component:Message } ]

5.3.4 路由链接:Home.vue
News Message

5.4 缓存路由组件对象
5.4.1 理解
  • 默认情况下,被切换的路由组件对象会死亡释放,再次回来时是重新创建的
  • 如果可以缓存路由组件对象,可以提高用户体验
5.4.2 编码实现

5.5 向路由组件传递数据
5.5.1 方式1:路由路径携带参数(param/query)
  • 配置路由
children:[ { path:'mdetail/:id', component:MessageDetail } ]

  • 路由路径
{{m.title}}

  • 路由组件中读取请求参数
this.$route.params.id

5.5.2 方式2:属性携带数据
5.6 编程式路由导航
相关API
  • this.$router.push(path):相当于点击路由链接(可以返回当前路由界面)
  • this.$router.replace(path):用新路由替换当前路由(不可以返回当前路由界面)
  • this.$router.back():请求(返回)上一个记录路由
  • this.$router.go(-1):请求(返回)上一个记录路由
  • this.$router.go(1):请求下一个记录路由
5.6.2 代码实现
pushShow (id) { this.$router.push(`/home/message/detail/${id}`) }

6.1 说明
  • 分析vue作为一个MVVM框架的基本实现原理
    • 数据代理
    • 模板解析
    • 数据绑定
  • 不直接看vue.js的源码
  • 剖析github上仿vue实现的MVVM库
  • 地址:https://github.com/DMQ/mvvm
6.2 准备知识
  • [].slice.call(lis):将伪数组转换为真数组
  • node.noteType:得到节点类型
  • Object.defineProperty(obj,propName,{}):给对象添加/修改属性(指定描述符)
    • configurable:true/false 是否可以重新define
    • enumerable:true/false 是否可以枚举(for…in/keys())
    • value:指定初始值
    • writable:true/false value是否可以修改
    • get:回调函数,用来得到当前属性值
    • set:回调函数,用来监视当前属性值的变化
  • Object.keys(obj):得到对象自身可枚举的属性名的数组
  • DocumentFragment:文档碎片(高效批量更新多个节点)
  • obj.hasOwnProperty(prop):判断prop是否是obj自身的属性
Title - 锐客网
MVVMd
  • test1
  • test2
  • test3
type="text/javascript"> //1. [].slice.call(lis): 根据伪数组生成对应的真数组 const lis = document.getElementsByTagName('li') // lis是伪数组(是一个特别的对象, length和数值下标属性) console.log(lis instanceof Object, lis instanceof Array) // 数组的slice()截取数组中指定部分的元素, 生成一个新的数组[1, 3, 5, 7, 9], slice(0, 3) // slice2() Array.prototype.slice2 = function (start, end) { start = start || 0 end = start || this.length const arr = [] for (var i = start; i < end; i++) { arr.push(this[i]) } return arr } const lis2 = Array.prototype.slice.call(lis)// lis.slice() console.log(lis2 instanceof Object, lis2 instanceof Array) // lis2.forEach()//2. node.nodeType: 得到节点类型 const elementNode = document.getElementById('test') const attrNode = elementNode.getAttributeNode('id') const textNode = elementNode.firstChild console.log(elementNode.nodeType, attrNode.nodeType, textNode.nodeType)//3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符) const obj = { firstName: 'A', lastName: 'B' } //obj.fullName = 'A-B' Object.defineProperty(obj, 'fullName', { // 属性描述符:// 数据描述符//访问描述符 // 当读取对象此属性值时自动调用, 将函数返回的值作为属性值, this为obj get () { return this.firstName + "-" + this.lastName }, // 当修改了对象的当前属性值时自动调用, 监视当前属性值的变化, 修改相关的属性, this为obj set (value) { const names = value.split('-') this.firstName = names[0] this.lastName = names[1] } })console.log(obj.fullName) // A-B obj.fullName = 'C-D' console.log(obj.firstName, obj.lastName) // C DObject.defineProperty(obj, 'fullName2', { configurable: false, //是否可以重新define enumerable: true, // 是否可以枚举(for..in / keys()) value: 'A-B', // 指定初始值 writable: false // value是否可以修改 }) console.log(obj.fullName2)// A-B obj.fullName2 = 'E-F' console.log(obj.fullName2) // A-B /*Object.defineProperty(obj, 'fullName2', { configurable: true, enumerable: true, value: 'G-H', writable: true })*///4. Object.keys(obj): 得到对象自身可枚举属性组成的数组 const names = Object.keys(obj) console.log(names) //5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性 console.log(obj.hasOwnProperty('fullName'), obj.hasOwnProperty('toString'))// true false//6. DocumentFragment: 文档碎片(高效批量更新多个节点) // document: 对应显示的页面, 包含n个elment一旦更新document内部的某个元素界面更新 // documentFragment: 内存中保存n个element的容器对象(不与界面关联), 如果更新framgnet中的某个element, 界面不变 /*
  • test1
  • test2
  • test3
*/ const ul = document.getElementById('fragment_test') // 1. 创建fragment const fragment = document.createDocumentFragment() // 2. 取出ul中所有子节点取出保存到fragment let child while(child=ul.firstChild) { // 一个节点只能有一个父亲 fragment.appendChild(child)// 先将child从ul中移除, 添加为fragment子节点 }// 3. 更新fragment中所有li的文本 Array.prototype.slice.call(fragment.childNodes).forEach(node => { if (node.nodeType===1) { // 元素节点
  • node.textContent = 'atguigu' } })// 4. 将fragment插入ul ul.appendChild(fragment)

  • 6.3 数据代理
    • 数据代理:通过一个对象代理对另一个对象(在前一个对象内部)中属性的操作(读/写)
    • vue数据代理:通过vm对象来代理data对象中所有属性的操作
    • 好处:更方便的操作data中的数据
    • 基本实现流程
      • 通过Object.defineProperty()给vm添加与data对象的属性对应的属性描述符
      • 所有添加的属性都包含getter/setter
      • getter/setter内部去操作dta中对应的属性数据
    代码实现:
    数据代理 - 锐客网
    type="text/javascript" src="https://www.it610.com/article/js/mvvm/compile.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/mvvm.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/observer.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/watcher.js"> type="text/javascript"> const vm = new MVVM({ el: "#test", data: { name: '张三2' } }) console.log(vm.name)// 读取的是data中的name,vm代理对data的读操作 vm.name = '李四2' // 数据保存到data中的name上, vm代理对data的写操作 console.log(vm.name, vm._data.name)

    6.4 模板解析
    6.4.1 模板解析的基本流程
    • 将el的所有子节点取出,添加到一个新建的文档fragment对象中
    • 对fragment中的所有层次子节点递归进行编译解析处理
      • 对大括号表达式文本节点进行解析
      • 对元素节点的指令属性进行解析
        • 事件指令解析
        • 一般指令解析
    • 将解析后的fragment添加到el中显示
    6.4.2 模板解析1:大括号表达式解析
    • 根据正则对象得到匹配出的表达式字符串:子匹配/RegExp.$1 name
    • 从data中取出表达式对应的属性值
    • 将属性值设置为文本节点的textContent
    模板解析_表达式_vue - 锐客网
    {{name}}
    type="text/javascript" src="https://www.it610.com/article/js/mvvm/compile.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/mvvm.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/observer.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/watcher.js"> type="text/javascript"> new MVVM({ el: '#test', data: { name: 'SADAMU' } })

    6.4.3 模板解析2:事件指令解析
    • 从指令名中取出事件名
    • 根据指令的值(表达式)从methods中得到对应的事件处理函数对象
    • 给当前元素节点绑定指定事件名和回调函数的dom事件监听
    • 指令解析完后,移除此指令属性
    模板解析_事件指令 - 锐客网
    type="text/javascript" src="https://www.it610.com/article/js/mvvm/compile.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/mvvm.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/observer.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/watcher.js"> type="text/javascript"> new MVVM({ el: '#test', data: { msg: 'hello atguigu' }, methods: { test () { alert(this.msg) } } })

    6.4.4 模板解析3:一般指令解析
    • 得到指令名和指令值(表达式) text/html/class msg/myClass
    • 从data中根据表达式得到对应的值
    • 根据指令名确定需要操作元素节点的什么属性
      • v-text—textContent属性
      • v-html—innerHTML属性
      • v-class—className属性
    • 将得到的表达式的值设置到对应的属性上
    • 移除元素的指令属性
    模板解析_一般指令 - 锐客网 > .aclass { color: red; } .bClass { font-size: 30px; }


    xxxxxx
    type="text/javascript" src="https://www.it610.com/article/js/mvvm/compile.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/mvvm.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/observer.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/watcher.js"> type="text/javascript"> new MVVM({ el: '#test', data: { msg: '尚硅谷', myClass: 'aclass' }, methods: { test () { alert(this.msg) } } })

    6.5 数据绑定
    6.5.1 数据绑定 一旦更新了data中的某个属性数据,所有界面上直接使用或间接使用此属性的节点更新
    6.5.2 数据劫持
    • 数据劫持是vue中用来实现数据绑定的一种技术
    • 基本思想:通过defineProperty()来监视data中所有属性(任意层次)数据的变化,有变化就去更新界面
    6.5.3 四个重要对象
    • Observer
      • 用来对data所有属性数据进行劫持的构造函数
      • 给data中所有属性重新定义属性描述(get/set)
      • 为data中的每个属性创建对应的dep对象
    • Dep(Depend)
      • data中的每个属性(所有层次)都对应一个dep对象
      • 创建的时机
        • 在初始化define data中各个属性时创建对应的dep对象
        • 在data中的某个属性值被设置为新的对象时
      • 【学习笔记|Vue的基础入门及使用】对象的结构
        { id,//每个dep都有一个唯一的id subs//包含n个对应watcher的数组(subscribes的简写) }

      • subs属性说明
        • 当watcher被创建时,内部将当前watcher对象添加到对应的dep对象的subs中
        • 当此data属性的值发生改变时,subs中所有的watcher都会受到更新的通知,从而最终更新对应的界面
    • Compiler
      • 用来解析模板页面的对象的构造函数(一个实例)
      • 利用compile对象解析模板页面
      • 每解析一个表达式(非事件指令)都会创建一个对应的watcher对象,并建立watcher与dep的关系
      • complie与watcher的关系:一对多的关系
    • Watcher
      • 模板中每个非事件指令或表达式都对应一个watcher对象
      • 监视当前表达式数据的变化
      • 创建的时机:在初始化编译模板时
      • 对象的组成
        { vm,//vm对象 exp,//对应指令的表达式 cb,//当表达式所对应的数据发生改变的回调函数 value,//表达式当前的值 depIds//表达式中各级属性所对应的dep对象的集合对象 //属性名为dep的id,属性值为dep }

    • 总结:dep与watcher的关系:多对多
      • data中的一个属性对应一个dep,一个dep中可能包含多个watcher(模板中有几个表达式使用到了同一个属性)
      • 模板中一个非事件表达式对应一个watcher,一个watcher中可能包含多个dep(表达式是多层的:a.b)
      • 数据绑定使用到2个核心技术
        • defineProperty()
        • 消息订阅与发布
    代码实现
    数据劫持-数据绑定 - 锐客网
    {{name}}


    type="text/javascript" src="https://www.it610.com/article/js/mvvm/compile.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/mvvm.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/observer.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/watcher.js"> type="text/javascript"> new MVVM({ el: '#test', data: { name: 'sadamu',// dep0 wife: { // dep1 name: 'binbin', // dep2 age: 18 // dep3 } }, methods: { update () { this.name = 'avatar' } } })

    6.6 MVVM原理分析
    学习笔记|Vue的基础入门及使用
    文章图片

    6.7 双向数据绑定
    • 双向数据绑定是建立在单向数据绑定(model=>View)的基础之上的
    • 双向数据绑定的实现流程
      • 在解析v-model指令时,给当前元素添加input监听
      • 当input的value发生改变时,将最新的值赋值给当前表达式所对应的data属性
    代码实现
    数据双向绑定 - 锐客网
    {{msg}}
    type="text/javascript" src="https://www.it610.com/article/js/mvvm/compile.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/mvvm.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/observer.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/watcher.js"> type="text/javascript"> new MVVM({ el: '#test', data: { msg: 'haha' } })

    第七章 Vuex 7.1 Vuex理解
    7.1.1 vuex是什么
    • github站点:https://github.com/vuejs/vuex
    • 在线文档:https://vuex.vuejs.org/zh-cn/
    • 简单来说,对vue应用中多个组件的共享状态进行集中式的管理(读/写)
    7.1.2 状态自管理应用
    • state:驱动应用的程序源
    • view:以声明方式将state映射到视图
    • actions:响应在view上的用户输入导致的状态变化(包含n个更新状态的方法)
      学习笔记|Vue的基础入门及使用
      文章图片
    7.1.3 多组件共享状态的问题
    • 多个视图依赖于同一状态
    • 来自不同视图的行为需要变更同一状态
    • 以前的解决办法
      • 将数据以及操作数据的行为都定义在父组件
      • 将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
    • vuex就是用来解决这个问题的
    7.2 vuex核心概念和API
    7.2.1 state
    • vuex管理的状态对象
    • 它应该是唯一的
      const state={ xxx:initValue }

    7.2.2 mutations
    • 包含多个直接更新state的方法(回调函数)的对象
    • 谁来触发:action中的commit(‘mutation名称’)
    • 只能包含同步的代码,不能写异步代码
      const mutations={ yyy(state,{data1}){ //更新state的某个属性 } }

    7.2.3 actions
    • 包含多个事件回调函数的对象
    • 通过执行:commit()来触发mutation的调用,间接更新state
    • 谁来触发:组件中:$store.dispatch(‘action名称’,data1) //‘zzz’
    • 可以包含异步代码(定时器,ajax)
      const actions={ zzz({commit,state},data1){ commit('yyy',{data1}) } }

    7.2.4 getters
    • 包含多个计算属性(get)的对象
    • 谁来读取:组件中:$store.getters.xxx
      const getters={ mmm(state){ return ... } }

    7.2.5 modules
    • 包含多个module
    • 一个module是一个store的配置对象
    • 与一个组件(包含有共享数据)对应
    7.2.6 向外暴露store对象
    export default new Vuex.Store({ state, mutations, actions, getters })

    7.2.7 组件中
    import {mapState,mapGetters,mapActions} from 'vuex' export default{ computed:{ ...mapState(['xxx']), ...mapGetters(['mmm']), }, methods:mapActions(['zzz']) }{{xxx}}{{mmm}}@click="zzz(data)"

    7.2.8 映射store
    import store from './store' new Vue({ store })

    7.2.9 store对象
    • 所有用vuex管理的组件中都躲了一个属性store,它就是一个store对象
    • 属性:
      • state:注册的state对象
      • getters:注册的getters对象
    • 方法:
      定是建立在单向数据绑定(model=>View)的基础之上的
    • 双向数据绑定的实现流程
      • 在解析v-model指令时,给当前元素添加input监听
      • 当input的value发生改变时,将最新的值赋值给当前表达式所对应的data属性
    代码实现
    数据双向绑定 - 锐客网
    {{msg}}
    type="text/javascript" src="https://www.it610.com/article/js/mvvm/compile.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/mvvm.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/observer.js"> type="text/javascript" src="https://www.it610.com/article/js/mvvm/watcher.js"> type="text/javascript"> new MVVM({ el: '#test', data: { msg: 'haha' } })

    第七章 Vuex 7.1 Vuex理解
    7.1.1 vuex是什么
    • github站点:https://github.com/vuejs/vuex
    • 在线文档:https://vuex.vuejs.org/zh-cn/
    • 简单来说,对vue应用中多个组件的共享状态进行集中式的管理(读/写)
    7.1.2 状态自管理应用
    • state:驱动应用的程序源
    • view:以声明方式将state映射到视图
    • actions:响应在view上的用户输入导致的状态变化(包含n个更新状态的方法)
    [外链图片转存中…(img-44Q93wcS-1590936591436)]
    7.1.3 多组件共享状态的问题
    • 多个视图依赖于同一状态
    • 来自不同视图的行为需要变更同一状态
    • 以前的解决办法
      • 将数据以及操作数据的行为都定义在父组件
      • 将数据以及操作数据的行为传递给需要的各个子组件(有可能需要多级传递)
    • vuex就是用来解决这个问题的
    7.2 vuex核心概念和API
    7.2.1 state
    • vuex管理的状态对象
    • 它应该是唯一的
      const state={ xxx:initValue }

    7.2.2 mutations
    • 包含多个直接更新state的方法(回调函数)的对象
    • 谁来触发:action中的commit(‘mutation名称’)
    • 只能包含同步的代码,不能写异步代码
      const mutations={ yyy(state,{data1}){ //更新state的某个属性 } }

    7.2.3 actions
    • 包含多个事件回调函数的对象
    • 通过执行:commit()来触发mutation的调用,间接更新state
    • 谁来触发:组件中:$store.dispatch(‘action名称’,data1) //‘zzz’
    • 可以包含异步代码(定时器,ajax)
      const actions={ zzz({commit,state},data1){ commit('yyy',{data1}) } }

    7.2.4 getters
    • 包含多个计算属性(get)的对象
    • 谁来读取:组件中:$store.getters.xxx
      const getters={ mmm(state){ return ... } }

    7.2.5 modules
    • 包含多个module
    • 一个module是一个store的配置对象
    • 与一个组件(包含有共享数据)对应
    7.2.6 向外暴露store对象
    export default new Vuex.Store({ state, mutations, actions, getters })

    7.2.7 组件中
    import {mapState,mapGetters,mapActions} from 'vuex' export default{ computed:{ ...mapState(['xxx']), ...mapGetters(['mmm']), }, methods:mapActions(['zzz']) }{{xxx}}{{mmm}}@click="zzz(data)"

    7.2.8 映射store
    import store from './store' new Vue({ store })

    7.2.9 store对象
    • 所有用vuex管理的组件中都躲了一个属性store,它就是一个store对象
    • 属性:
      • state:注册的state对象
      • getters:注册的getters对象
    • 方法:
      • dispatch(actionName,data):分发调用action
    小结 这篇权当是学习Vue的一个基础,更多内容,我打算做一个网站,遇到了再更新吧。

      推荐阅读