vue实战开发
分享指南
1.渐进式框架
2.vue中两个核心点
3.虚拟DOM
4.MVVM模式
5.vue实例
6.声明式渲染
7.指令
8.模板
基础语法
vue实例
一.vue介绍
1.渐进式框架vue
vue是什么
构建用户界面的渐进式框架
只关注视图层(view)
2.vue中两个核心点
响应的数据绑定
当数据发生改变---->自动更新视图
利用Object.definedProperty中的setter/getter代理数据,监控对数据的操作
组合的视图组件
ui页面映射为组件树
划分组件可维护 可重用可测试
3.虚拟DOM(virtual DOM)
运行js的速度是很快的,大量的操作DOM就会很慢.时长在更新数据后会重新渲染页面,这样造成在没有改变数据的地方也重新渲染DOM节点,这样就造成了很大程度上的资源浪费.
利用在内存中生成与真实DOM与之对应的数据结构,这个在内存中生成的结构称之为虚拟DOM.
当数据发生变化时,能够智能地计算出重新渲染组件的最小代价并应用到DOM操作上.
4.MVVM模式
M: Model数据模型
V: view视图模板
VM: view-Model 视图模型
5.vue实例
渐进式框架学习提纲
基础语法
... | |
---|---|
vue实例 | 模板语法 |
计算属性 | class和style绑定 |
条件和列表渲染 | 事件处理器 |
表单控件绑定 | 组件 |
高级进阶
... | |
---|---|
vue插件编写 | mixin混合 |
过度效果 | 自定义制定 |
vue-router:路由系统的使用 | vueX:状态管理器 |
构建工具
... | |
---|---|
node.js:javascript运行环境 | webpage:模块管理和打包工具 |
vue-cli:脚手架配置 |
vue实例
每一个应用都是通过vue这个构造函数创建根实例(root instance)启动 new Vue(选项对象)
需要传入选项对象,对象包含挂在元素,数据,模板,方法等...
el:挂载元素选择器 String|HemlElement
data: 代理数据 Object|Function
methods:定义方法 Object
<div id="demo">
<input type="text" id="" v-model="message">
<p v-on:click="clickHandle">{{message}}</p>
</div>
<script>
var data={message:"hello"}
var vm=new Vue({
el:"#demo",
data:data,
methods:{
clickHandle:function(){
alert("click")
}
}
})
</script>
vue代理data数据
每个vue实例都会代理其data对象里所有的属性,这些被代理的属性是响应的.新添加的属性不具备响应功能,改变后不会更新视图.
vue实例自身属性和方法
暴露自身的属性和方法,以$开头 例如 :$el $data...
6.声明与渲染
声明式
只需要声明在哪里(where)做什么(what),而无需关心如何实现(how)
命令式
需要以具体代码表达在哪里(where)做什么(what),如何实现(how)
例子: 求数据中每一项的倍数
命令式 使用for虚幻拿出每一项然后求值完成,再放入另一数组中
声明式:使用map方法,关注如何求值
vue声明式渲染
初始化根实例,vue自动将数据绑定在DOM模板上
7.指令
什么是指令
是一种特殊的自定义行间属性
指令的职责就是当期表达式的值改变时相应的将某些行为应用到DOM上
在Vue中,指令以V-开头
vue中的内置指令
- v-bind 动态的绑定数据。简写为 :
- v-on 绑定事件监听器。简写为 @
- v-text 更新数据,会覆盖已有结构
- v-html 可以解析数据中的html结构
- v-show 根据值的真假,切换元素的display属性
- v-if 根据值的真假,切换元素会被销毁,重建
- v-else-if 多条件判断,为真则渲染
- v-else 条件都不符合渲染
- v-for 基于源数据多次渲染元素或模板块
- v-model 在表单控件元素航创建双向数据绑定
- v-pre 跳过元素和子元素的编译过程
- v-once 只渲染一次,随后数据更新不重新渲染
- v-cloak 隐藏未变异的Mustache语法,css中设置[v-cloak]{display:none}
8.模板
A.html模板
html模板
基于DOM的模板,模板都是可解析的有效的HTML
插值
文本插值:使用"Mustache"语法(双大括号) {{value}}
作用:替换实例上的属性值,当值改变时,插值内容会自动更新
原生的html:双大括号输出的是文本,不会解析html(如要解析,添加指令v-html)
属性: 使用v-bind进行绑定,可以响应变化
使用JavaScript表达式:写简单的表达式
示例代码: 插值原生的HTML在双大括号输出的是文本,不会解析成HTML 这就要用到v-html
<div id="demo">
<span v-html="html"></span>
{{1+2}} //一些简单的表达式
{{true?"yes":"no"}} //三目可以 但是不要写if语句
</div>
<script>
/*数据*/
let obj={
html:"<div>这是一段html</div>"
}
var vm=new Vue({
el:"#demo",
data:obj
})
</script>
/*不要在模板里做过多的逻辑处理*/
B.字符串模板
template字符串
- template选项对象的属性
- 模板将会替换挂载的元素,挂在元素的内容将被忽略
- 根节点只能有一个
- 将HTML结构写在一对script标签中,设置 type="x-template"
示例代码:===>输出内容 : 这是一段str 123456
<!--模板-->
<div id="demo">
<span>我是span里的原始内容</span>
</div>
<script>
/*数据*/
let obj={
html:"<div>这是一段html</div>",
abc:"123456"
}
var str="<div>这是一段str {{abc}}</div>"
var vm=new Vue({
el:"#demo",
data:obj,
template:str
})
</script>
示例代码2 : 将HTML结构写在一对script标签中,设置 type="x-template"
<div id="demo">啊?</div>
<script type="x-template" id="temp">
<div>{{abc}}
<span>我是span里的原始内容</span>
</div>
</script>
<script>
/*数据*/
let obj={
abc:"哈哈哈..."
}
var vm=new Vue({
el:"#demo",
data:obj,
template:"#temp"
})
</script>
C.模板-render函数
render函数
- render选项对象的属性
- createElement(标签名,[数据对象],子元素);
- 子元素为文本或数组
示例一:
<div id="demo"><span :class='{red:addClass}'>hello vue</span></div>
<script>
/*数据*/
let obj={
addClass:true
}
var vm=new Vue({
el:"#demo",
data:obj
});
</script>
render函数示例:
<style> .bg{background:yellow}</style>
<div id="demo"></div>
<script>
/*数据*/
let obj={
addClass:true
}
var vm=new Vue({
el:"#demo",
data:obj,
render:function(createElement){
return createElement(
"ul",
{
class:{bg:true},
style:{
fontSize:"50px",
listStyle:"none"
},
attrs:{
key:"我是value啊"
},
domProps:{
innerHTML:"<li>我是html</li>"
}//谨慎使用
},
[
createElement("li",1),
createElement("li",2),
createElement("li",3)
]
)
}
})
</script>
数据对象属性
class:{} //绑定class,和v-bind:class
一样的API (绑定和原生可以共存)
style:{} //绑定样式,和v-bind:style
一样的API
attrs:{} //添加行间属性
domProps:{} //DOM元素属性
on:{} //绑定事件
nativeOn:{} //监听原生事件
directives:{} //自定义指令
scopedSlots:{} //slot作用域
slot:{} //定义slot名称
key:"key" //给元素添加唯一标识
ref:"ref" //引用信息
二 案例:增删便签 深入讲解 指令&模板
列表渲染
-
v-for指令
根据一组数据的选项列表进行渲染
语法 :
value,key in items
value,key of items
变异方法
vue提供一组方法,对数组进行操作的时候,会触发视图更新
push() pop() shift() unshift() splice() sort() reverce()
事件处理器
-
v-on指令
用来监听DOM事件触发代码
语法: v-on:eventName="evnetHandle"
指令简写: @
事件处理函数,写在methods中统一管理
事件对象 , 在事件处理函数中获取 , 内联事件处理函数执行 , 传入事件对象 $event
事件修饰符 : 事件处理函数只有纯粹的逻辑判断 , 不处理DOM事假的细节
例如:阻止冒泡,取消默认行为,判断按键
事件修饰符
- 事件修饰符
事件处理函数只有纯粹的逻辑判断,不处理DOM事件的细节 例如,阻止冒泡,取消默认行为,判断按键
修饰符的位置:v-on;eventName.修饰符
修饰符: .stop .prevent .capture .self .once
按键修饰符: .enter .tab .delete .esc .space .up .down .left .right .ctrl .alt .shift .meta .键值
条件渲染
-
v-show指令
根据表达式的值,用来显示/隐藏元素
语法: v-show="表达式"
元素会被渲染在页面中,只根据表达式的值进行css切换
动态class
-
动态绑定class
class也为元素的属性,可以使用v-bind:class
语法
:class="{className:表达式}"
表达式值为true 添加className
表达式值为false不添加className:class="[className,classname]"
自定义指令
-
自定义指令
除了vue内置的指令,可以自己设置指令
选项对象的directives属性
{
directives:{ }
}
钩子函数:
update被绑定元素所在的模板更新时调用
钩子函数中参数:
el:指令所绑定的元素,可以用来直接操作DOM
binding:一个对象
value:指令的绑定值
计算数据
-
为什么要使用计算属性
模板是为了描述视图的结构,模板中放入太多逻辑,导致模板过重且难以维护.
在计算一个计算属性时,vue.js更新它的依赖列表并缓存结果,只有当其中一个依赖发生的变化,缓存的结果才无效.
语法:
在选项对象中
{
...
computed:{}
}
五.watch深度监控数据
六.利用hash过滤数据
onhashchange 事件在当前 URL 的锚部分(以 '#' 号为开始) 发生改变时触发 。
锚部分的实例:指定当前 URL 为
http://www.example.com/test.htm#part2 - 这个 URL 中的锚部分为 #part2。
你可以使用以下方式调用事件:
- 通过设置Location 对象 的 location.hash 或 location.href 属性修改锚部分。
- 使用不同书签导航到当前页面(使用"后退" 或"前进"按钮)
- 点击链接跳转到书签锚
七.什么是组件
组件化开发
-
什么是组件?
WEB中的组件其实就是页面组成的一部分,好比是电脑中的每一个元件(如硬盘,键盘,鼠标),它是一个具有独立的逻辑和功能或界面,同时又能根据规定的接口规则进行相互融合,变成一个完整的应用.
页面就是由一个个类似这样的部分组成的,比如导航,列表,弹窗,下拉菜单等.页面只不过是这些组件的容器,组件自由组合形成功能完整的界面,当不需要某个组件,或者想要替换某个组建时,可以随时进行替换和删除,而不影响整个应用的运行.
前端组件化的核心思路就是将一个巨大复杂的东西拆分成粒度合理的小东西 -
使用组件的好处
提高开发效率
方便重复使用
简化调整步骤
提升整个项目的可维护性
便于协同开发
vue中的组件
-
vue中的组件
vue中组件是一个自定义标签,Vue.js的编辑器为它添加特殊功能
vue也可以扩展原生的html元素,封装可重用的代码
组件的基本组成 : 样式结构 行为逻辑 数据
注册组件
-
全局注册
可以再任何模板中使用,使用之前要先注册
语法: 使用Vue.component(组件名,选项对象)
组件名命名约定:驼峰(camelCase),烤串(kebab-case)
在html中使用组件:
使用烤串(kebab-case)命名法
使用: <my-component></my-component> -
局部注册
在组件实例中通过选项对象注册,只在所注册的作用域中使用
{
components:{
组件名:选项对象
}
}
局部注册:
new Vue({
el:"#app",
components:{
"custom-select":{
template:`<section></section>`
}
}
})
全局注册:
Vue.component("custom-select",{
template:`<section class="warp"></section>`
})
组件间通信
父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件
父组件-->子组件
组件实例的作用域是孤立的,不能在子组件直接用父组件的数据
可以在组件上使用自定义属性绑定数据,在组件中需要显示的用props声明自定义属性名子组件-->父组件
需要用到自定义事件,父组件用$on监听自定义事件,$emit触发父组件所关心的自定义事件
八.使用props传递数据
<div id="app-7">
<ol>
<!--
现在我们为每个 todo-item 提供 todo 对象
todo 对象是变量,即其内容可以是动态的。
我们也需要为每个组件提供一个“key”,稍后再
作详细解释。
-->
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
v-bind:key="item.id">
</todo-item>
</ol>
</div>
Vue.component('todo-item', {
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
})
var app7 = new Vue({
el: '#app-7',
data: {
groceryList: [
{ id: 0, text: '蔬菜' },
{ id: 1, text: '奶酪' },
{ id: 2, text: '随便其它什么人吃的东西' }
]
}
})
组件中的data必须是函数
每个组件都是相互独立的,如果他们共用一个对象,在更改一个组件数据的时候,会影响其他组件,如果是函数的话,每个组件都有自己独立的数据,相互之间不会影响.
九.特殊is属性扩展原生html元素
受限制的元素
-
DOM模板解析
Vue是在浏览器解析和标准化 HTML后才能获取模板内容,所以有些元素限制了能被它包裹的元素
例如: ul中只能放li; select中只能放option
某些元素中放入了自定义元素,不符合W3C标准,最终会解析错误
变通的方式是使用特殊属性 is来扩展HTML标签功能
十.v-bind动态绑定数据&十一.利用自定义事件通信
案例:
<div id="app">
<h2>自定义下拉框</h2>
<custom-select btn-value="查询" v-bind:list="list1"></custom-select>
<custom-select btn-value="搜索" v-bind:list="list2"></custom-select>
</div>
<script>
//注册组件 全局注册
Vue.component("custom-select",{
data:function(){
return{sel:false, val:""}
},
props:["btnValue","list"],
template:`<section class="warp">
<div class="searchIpt clearFix">
<div class="clearFix">
<input type="text" class="keyWord" v-bind:value="val" @click="sel=!sel"/>
<input type="button" v-bind:value="btnValue">
<span></span>
</div>
<custom-list v-show="sel" v-bind:list="list" v-on:receive="changeValue"></custom-list>
</div>
</section>`,
methods:{
changeValue:function(value){
console.log(value)
this.val=value;
}
}
})
Vue.component("custom-list",{
props:["list"],
template:`<ul class="list" >
<li v-for="item in list" @click="selectValueHandle(item)">{{item}}</li>
</ul>`,
methods:{
selectValueHandle:function(item){
//子组件中有交互 数据放到input当中去 告知父级,改变val的值 需要触发一个自定义事件
this.$emit('receive',item) //this.item
}
}
})
var data={
list1:["北京","上海","杭州"],
list2:["17,10,25","18,1,1","17,12,22"]
}
new Vue({
el:"#app",
data:data
})
</script>
十二.单向数据流
什么是单向数据流
数据从父组件流向(传递)给子组件,只能单向绑定
在子组件内部不应该修改父组件传递过来的数据
- 改变prop的情况:
1.作为data中局部数据的初始值使用
2.作为子组件种的computed树属性
<div id="app">
<custom-component :count="count"></custom-component>
</div>
<script>
Vue.component('custom-component',{
props:['count'],
data(){
return {
incrementCount:this.count//作为局部这个组件的data的初始值
}
},
computed:{
incrementCount2(){
return this.incrementCount;
}
},
template:`
<div>
<h2>我是一个自定义组件</h2>
<input type="button" value="改变count的值" @click="changeCount">
{{incrementCount2}}
</div>
`,
methods:{
changeCount(){
this.incrementCount++;
}
}
})
var vm=new Vue({
el:"#app",
data:{count:0},
methods:{
}
})
</script>
十三.props验证
组件可以为props指定验证要求,如果未指定验证要求,vue会发出警告
props:{
propA:Number,//指定类型
propB:[String,Number],//多种类型
propC:{type:String,required:true},//字符串类型,默认值为100
propD:{type:Number,default:100}.//字符串类型,默认值为100
propE:{type:Number,default:function(){
return 1000
}
},
//自定义验证规则
propF:{validator:function(value){return value>10}}
验证类型为原生构造器:String,Number,FunctionObject,Boolean,Array