Vue 2 笔记
介绍
Vue是一套渐进式框架,用来动态构建用户界面(view)。
基本认识
MVVM模式
M:model,数据对象(data中的数据)
V:view,模板页面(页面中所显示的内容),是动态的html页面
VM:VueModel,new 的Vue对象,也就是vm对象
模板页面(view)语法
双大括号表达式:显示数据
<!-- textContent 整个内容-->
<p>{{msg}}</p>
<!-- textContent 整个内容-->
<p v-text="msg"></p>
<!-- innerHTML 标签内文本 -->
<p v-html="msg"></p>
指令,以v-开头的自定义标签属性
强制数据绑定
v-bind:xxx=“yyy”
简写::xxx=“yyy”
<!-- 完整写法 -->
<img v-bind:src='imgUrl' >
<!-- 简洁写法 -->
<img :src='imgUrl' >
绑定事件监听
v-on:事件名=“事件回调”
简写:@事件名=“事件回调”
<button v-on:click="callback">test1</button>
<!-- 可自定义参数 -->
<button @click="callback2('abc')">test2</button>
<!-- 还可传变量 -->
<button @click="callback2(imgUrl)">传变量</button>
计算属性与监视
计算属性
模板页面(view)适用于简单的声明式逻辑
计算属性是vm实例对象中的另一个配置对象,适用于复杂逻辑
默认计算属性
当计算属性中只有一个回调函数时,此回调函数默认是getter,可显示当前属性数据
// 此回调函数什么时候执行:1.初始化显示时执行,2.相关属性数据发生变化时
// 用来干什么:计算并返回当前属性的值
computed: {
//计算属性中的一个方法,方法的返回值为属性值,回调函数
fullName1(){
return this.firstName + '_' + this.lastName
},
}
计算属性高级
通过getter(计算属性的get方法) 实现对属性数据的显示
通过setter(计算属性的set方法) 实现对属性数据的监视
computed:{
fullName:{
// 回调函数,计算并返回当前属性的值
// 回调函数的特点:1.你定义的,2.你没有调用,3.但最终执行了
// 回调函数用来干嘛的?什么时候被调用?
// 执行:当需要读取当前属性值的时候回调,用处:根据相关的数据计算并返回当前属性的值
get(){
return this.firstName+' '+this.lastName
},
// 回调函数,监视当前属性值的变化,当属性值发生改变时回调,更新相关的属性数据
//value就是fullName3的最新属性值
set(value){
// str.split()方法使用指定的分隔符字符串将一个str对象分割成子字符串数组
const names = value.split(' ')//以空格分开
this.firstName = names[0]
this.lastName = names[1]
}
}
// 调用get方法:
<h2>{{fullName}}</h2>
//调用set方法:
fn() {
this.fullName = '略略略'
}
监视
可配置监视对象
可在在数据变化时执行异步或开销较大的操作
//配置监视,可用来响应数据的变化
watch:{
//调用这个函数时说明firstName发生了变化
//会接收两个参数:1.新的值 2.旧的值
firstName:function(newVal, oldVal){
//this就是vm实例对象
console.log(this);
this.fullName = newVal + ' '+ oldVal;
}
}
调用$watch方法
// 所有vm实例对象的方法都以$符号开头
// 此方法与上面watch配置一样
vm.$watch("lastName",function(newVal, oldVal){
this.fullName = newVal +' '+ oldVal
})
//需要有vm的实例 例如: const vm = new Vue();
计算属性和监视的区别
1. 计算属性基于响应式依赖来缓存,初始化执行一次,如果没有监测到数据变化,多次访问数据时,计算属性会立即返回之前的计算结果,所以它可利用缓存做大量的数据计算。
2. 只要数据变化,计算属性就会改变,比监听属性watch简单且方便。
3. watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
强制绑定class和style
class/style绑定可用来实现动态样式效果的技术
class绑定
class=‘xxx’
xxx可以是字符串、对象、数组
<p class="cClass" :class="a">xxx是字符串</p>
<!-- <p :class="{aClass:false,bClass:true}">xxx是对象</p>
这样跟下面在data对象里设置isA的值为true是一样的 -->
<p :class="{aClass:isA,bClass:isB}">xxx是对象</p><!-- 用的多 -->
<p :class="['aClass','bClass']">xxx是数组</p>
style绑定
:style=’{color:activeColor,fontSize+“px”}’
其中activeColor/fontSize是data属性
<p :style="{color:activeColor,fontSize:fontSize+'px'}">hello world</p>
条件渲染
条件渲染指令
v-if 如果if中条件为真,则以此处内容渲染页面
v-else 如果if中条件为假,则以此处内容渲染页面
v-show 如果此处属性值为真,则以此处内容渲染页面,如果属性为假,则隐藏
区别
v-if 隐藏时,是将标签移除,切换消耗高。在运行时如果条件很少改变,则用v-if
v-show 不移除,而是通过改变元素的css属性display来实现显示与隐藏。如果需要频繁切换,则用v-show
列表渲染
<ul>
<li v-for="(p,index) in persons" :key="index">
{{index}}--{{p.name}}--{{p.age}}
<button @click="del(index)">删除</button>
<button @click="update(index,{name:'cat',age:25})">更新</button>
</li>
</ul>
<!-- v-for 可遍历数组、对象,并利用 key 管理可复用的元素 -->
<!-- key值 -->
因为 Vue 会尽可能高效地渲染元素,所以通常会复用已有元素而非从头开始渲染。
如果没有在两个可切换的输入框中分别加上唯一的key值,切换后,输入框中被输入的内容不会清除,会被复用
如果添加了key值,则向系统说明“这两个元素是独立的,不要复用他们”
事件处理
绑定监听
v-on:xxx=‘fn’
@xxx = ‘fn’
@xxxx = ‘fn(参数)’ , 默认事件形参:event (绑定监听时可不传参数event),隐含属性对象: $event
事件修饰符
<!-- 嵌套的元素,有事件冒泡,子元素的事件冒泡到父元素 -->
<div style="height: 200px;width: 200px;background-color: #bfa;" @click="test5">
<div style="height:100px; width: 100px; background-color: tomato;" @click.stop="test6"></div>
</div>
@xxx.stop
停止事件冒泡,相当于 event.stopPropagation()
@xxx.prevent
阻止事件的默认行为(a标签的自动跳转页面),相当于 event.preventDefault()
@xxx.passive
立即触发事件的默认行为,例如 scroll 滚动事件,提升移动端的性能
@xxx.once
点击事件只会触发一次
注意
在事件处理程序中调用 event.preventDefault() 等方法在js中很常见
但在 Vue 中要尽可能地只调用方法,代码只处理纯粹的数据逻辑,不处理 dom 事件
所以尽量少用事件修饰符来处理 dom 事件
表单输入绑定
<form action="/xxx" @submit.prevent="handleSubmit"><!-- 表单的原生方法onsubmit,提交表单 -->
<span>用户名:</span> <input type="text" v-model="username"><br>
<span>密码:</span><input type="password" v-model="password"><br>
</form>
v-model (双向数据绑定)自动收集数据,收集完之后就可使用ajax发送给后台
checkbox:
多选,收集到的数据为数组,data初始化数据时也要将其定义为数组,再为其写唯一的 value 值
radio:
单选,为每个选项写唯一的 value 值,后台收集的数据即 value 值
select:
下拉框,收集到的数据为数组,里面的元素为对象,包含标识符 id 和 name ,后台收集的数据为 id 值
vue 对象的生命周期
1. 初始化显示
beforeCreate()
created()
beforeMount()
mounted()
2. 更新显示
beforeUpdate()
updated()
3. 销毁 vue 实例
beforeDestory()
destoryed()
过滤器
<p>年月日:{{date | dateStr("YYYY-MM-DD")}}</p>
Vue.filter("dateStr",function(value,format){}
或者
new Vue({
filter: {
dateStr(date){}
}
})
内置指令
常用内置指令
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 对象通过 $refs 属性访问这个元素对象
v-cloak:防止闪现,与css配合:[ v-cloak ] { display:none },v-cloak 这个指令会一直保持在元素上,直到关联实例结束编译。将其与css样式结合可隐藏有这个属性的标签,直到实例准备完毕,即数据加载完成后才显示
<!-- 不赋值,v-cloak默认为true -->
<p v-cloak>{{tt}}</p>
/* 属性选择器,有这个属性的元素的样式被设置为 */
[v-cloak]{
display: none;
}
<p ref="text">{{tt}}~atguigu.com</p>
alert(this.$refs.text.textContent)
自定义指令
注册全局指令
/* "lower-text"为自定义的指令名 */
Vue.directive("lower-text",function(el,binding){
el.innerHTML=binding.value.toLowerCase()
})
注册局部指令
new Vue({
// 注册局部指令,配置一个对象
// 局部指令,只在当前vm管理范围内有效,即选择器 #demo内
directives:{
/* 对象的属性名平时可不写引号,但此时属性名特殊有-连接,就需要引号 */
"upper-text"(el,binding){
el.innerHTML=binding.value.toUpperCase()
}
}
使用指令
<p v-lower-text="msg1"></p>
插件
html文件中使用
引入插件库
将插件暴露在外,使其可用 window.myPlugin=myPlugin
声明使用插件 Vue.use(myPlugin)
vue 项目中使用
安装插件 npm i fastclick --save
main.js 中引入插件 import fastClick from ‘fastclick’
Vue.use(fastClick)
Vue项目的创建
Vue 脚手架 命令
1. ** npm install ** 安装依赖包
2. ** npm run serve ** 启动项目
3. ** npm bulid ** 项目打包,在命令行界面执行
安装
npm i webpack 项目文件名 ( vue-cli2 的创建方式)
或者 npm create 文件名 ( vue-cli3 的创建方式)
安装插件
npm i vuex --save ( --save 表示运行时也需要使用此插件,–save-dev 表示此插件只是开发时需要)
vue-axios:发送ajax请求
vue-router:路由
vuex:状态管理
vue-lazyload:图片懒加载
vue-scroller, better-scroll:页面滚动相关
mint-ui:基于 vue 的 UI 组件库(移动端)
element-ui:基于 vue 的 UI 组件库( PC 端)
项目的运行
npm run dev (vue-cli2 的运行方式)
npm run serve ( vue-cli3 的运行方式)
项目的打包
在本地对当前项目进行编译打包,最终生成一个dist文件夹
项目的发布
使用静态服务器打包
npm i -g serve (静态服务器就叫 serve)
serve dist (运行 dist 文件夹)
访问:http://localhost:5000
使用动态web服务器(tomcat)
修改配置:webpack.prod.conf.js
output: { publicPath: ‘/xxx/’ (打包文件夹的名称) }
重新打包:npm run bulid
修改 dist 文件夹为项目名称:xxx
将 xxx 拷贝到运行的 tomcat 的 webapps 目录下
访问:http://localhost:8080/xxx
项目文件夹概览
<!-- 看整体文件作用 -->
1. build 和 config 文件都是配置文件夹
2. config 文件夹里的 index.js 文件
有 port 端口号,两个项目运行时,要修改其中一个项目的端口号
autoOpenBrowser 自动打开浏览器,改为 true
3. node_modules 依赖
4. src 文件夹是源码目录,写的代码都是包含在里面
main.js 是入口文件,webpack.base.config.js 是它的配置
5. static 静态的,里面放一些全局的资源(样式、图片),可以在页面(index.html)里引用.gitkeep文件,专门 为git服务的里面
git有一个特点,如果static文件夹什么都诶有,它会自动忽略
如果不希望被忽略,则可以创建.getkeep文件,git就会将此文件夹版本控制起来
6. .babelrc文件
balel可以用来将es6语法转换为es5语法,jsx语法转js语法
jsx就是js+html,xml是html标签和一些自定义标签,可以看做js+html
.babelrc文件就是描述babel是怎么运行的,也就是babel的配置文件
7. .eslintrc.js
eslint的配置文件
8. .eslintignore文件
eslint会默认会一些文件做检查,如果希望它忽略哪些文件,就可以在此文件中配置
9. index.html 主页
其他的应用都是单页应用
10. package.json 文件
当前应用的描述文件
eslint
eslint 是一个代码规范检查工具
配置
手动修改
在文件 .elintrc.js 中的 rules 配置对象中修改规则为 ‘off’ 或者 ‘0’, 例如:‘indent’ : ‘off’ 或者 ‘0’
修改配置完成,需重新运行项目 npm run dev
安装插件 Prettier 自动修复格式
<!-- 报错信息 -->
Missing semicolon 缺少分号
Missing space before opening brace 左大括号前缺少空格
Trailing spaces not allowed 不允许尾随空格
Unexpected trailing comma 意外的尾随逗号
Multiple spaces found before ‘+’ 在“+”之前找到多个空格
A space is required after ‘,’ “,”后需要空格
Expected indentation of 4 spaces but found 6 预期缩进4个空格,但找到6个
Infix operators must be spaced 中缀运算符必须间隔
‘title’ is never reassigned. Use ‘const’ instead “标题”从未重新分配。改用“const”
vue 组件
main.js
src 文件夹中的 main.js 文件是入口文件,用来创建 vue 实例
/* 这个文件是入口js:要创建Vue实例
*/
// 1.引入vue
import Vue from 'vue'
// 2.1引入App.vue
import App from './App.vue'
// 2.创建Vue实例
new Vue({
el:'#app', // 根据index.html文件
// 将App.vue渲染到index.html中
// 2.1.先引入App.vue
// 2.2.映射标签名称
components:{
App
},
// 2.3 编译模板 ,内部的渲染函数会将模板挂载到html中去
template:'<App/>'
})
App.vue
App.vue 是根组件,最终是将 App.vue 渲染到 index.html 中,所以要在 App.vue 中引入所有的子组件
组件
一个组件就是局部功能界面,局部功能界面里相关的所有资源(css/js/img…)都是组件的一部分
组件化编码的基本流程
页面显示 --> 用户操作
数据在哪个组件里,更新数据的行为(方法或函数)就必须定义在哪个组件里
拆分组件
实现静态页面框架
在静态页面中初始化数据(将数据在组件间传递)
实现动态组件:数据交互:用户点击提交、删除等
确定数据是什么
为数据定义一个名称,确定它的类型
数据放到相应的组件中
–此数据只有一个组件使用时,就放到那个组件里即可
–此数据同时被几个组件使用,就需放到他们共同的父组件中
–组件间通信
组件间通信
props
父传子,子再传给自己的子组件,一层一层传递
$emit
将子组件数据传递给父组件
$refs
只用于父组件直接访问子组件数据,不适用三层嵌套关系
消息订阅与发布
可用于多重嵌套组件间的数据传递,可直接从根组件将数据传递到任意嵌套的组件
安装插件pubsub
npm i pubsub-js --save
订阅消息
相当于绑定事件回调函数,可在初始化显示时订阅:PubSub.subscribe(‘eventName’,mes => {})
发布消息
相当于触发事件回调函数:PubSub.publish(‘eventName’,index)
slot 插槽
传递的数据是标签数据,组件标签被反复使用时适用
子组件模板预留多个插槽位置,多个占位,但占位本身不显示东西,由父组件决定展示什么内容
在子组件占位(布局),在父组件中插入标签数据并做样式调整(内容)
$bus 事件总线
// 将vue实例作为事件总线,监听不同组件间事件变化,使得组件间通信
Vue.prototype.$bus = new Vue()
//在某个组件中发送事件
this.$bus.$emit("itemImageLoad")
// 在某个组件中监听itemImageLoad图片加载事件
this.$bus.$on('itemImageLoad', this.itemImgListener)
destroyed () {
// 离开组件时取消图片加载监听事件
this.$bus.$off('itemImageLoad', this.itemImgListener)
},
......
mixin 混入
创建 mixin.js 封装重复的代码
export const itemListenerMixin = { 创建混入对象
data()
components:{} 可混入所有vm的配置对象
methods: {}
}
在需要的组件中导入
mixins:[itemListenerMixin]
将组件封装为插件
将 Toast.vue 组件封装为插件
在toast文件夹下创建 index.js
const obj = {}
export default obj
main.js 中安装
import toast from 'components/common/toast'
Vue.use(toast)
返回 index.js 中封装
[引入Toast组件,并将其创建为组件对象]
import Toast from './Toast'
const obj={}
[调用Vue.use就是调用的对象的install方法函数] [默认会传一个Vue参数]
obj.install=function(Vue){
[将Toast创建为组件构造器]
const toastConstructor = Vue.extend(Toast)
[new组件构造器来创建一个组件对象]
const toast = new toastConstructor()
[将组件对象手动地挂载到元素上]
toast.$mount(document.createElement('div'))
[toast.$el对应的就是div,再将组件对象的模板添加进body里]
document.body.appendChild(toast.$el)
[将组件对象添加进prototype中,方便其他组件使用:this.$toast]
Vue.prototype.$toast = toast
}
[default是默认导出的obj,所以可以在导入时随便修改名字为toast]
export default obj
存储数据
sessionstorage
存储在内存中,当页面关闭时,数据就会被清除
localStorage
本地存储,将数据存储为文件,无论页面如何变化(关闭或刷新)都不会被清除数据,数据可长期保存
发表评论
还没有评论,快来抢沙发吧!