今天写了一天的时间,麻烦读者怀一颗感恩的心阅读哈~小编提前感谢大家咯
小编今天为大家推出一期vue全家桶续集~按照下述的xmind来哦,有兴趣的童鞋可以提前预习一下。。。
一.vue框架
1.项目的框架模式(MV*)
1.1.MVC架构模式
1.MVC的出现用在后端(全栈时代)。 2.M:model,模型,主要完成业务功能,在数据库相关的项目中,数据的增删改查。 V:view,视图,主要负责数据的显示(html+css)。 C:controller,控制器,主要负责每个业务的核心流程,在项目中体现在路由以及中间件上。 3.优缺点:
- 优点:
耦合度低、复用性高、生命周期成本低、部署快、可维护性高、有利于软件工程化管理。 - 缺点
由于模型和视图分离,这样给调试应用程序带来困难。
1.2MVP架构模式
1.MVP:Model View Presenter,分别表示数据、视图和发布层。是MVC架构的一种演变。 2.M:model,模型,主要完成业务功能,在数据库相关的项目中,数据的增删改查。 V:view,视图,主要负责数据的显示(html+css)。 p:Presenter负责业务流程的逻辑处理,Presenter是从Model中获取数据并提供给View层,Presenter还负责处理后端任务。 3.MVP模式与MVC模式的区别: MVP模式中的View不直接使用Model,而MVC模式中View可以绕过Controller,从Model中直接读取数据。
1.3MVVM架构模式
1.MVVM是Model-View-ViewModel,MVVM模式与MVP模式相似。唯一区别是MVVM模式采用的是数据双向绑定。
1.4总结
1.vue采用的是MVVM模式,M-V-VM,M是数据,V是视图,VM负责M与V相互通信。 2.架构是一种思维方式,是一种思考问题解决问题的思维。目的解决编程过程中模块内部高内聚、模块与模块直接的低耦合、可维护性、易测试等。 3.架构有利于做好代码的分工,配合。
二.vue框架的核心
1.vue框架的核心:数据驱动和组件化。
- 数据驱动:数据的变化驱动页面发生变化,不用操作DOM。(一定要切记幺,是不是有的宝宝一冲动,就想操作Dom啦)
- 组件化:把页面封装成若干个组件,把组件进行拼装,让页面的复用性达到最高。
三.初识vue框架(vue官网)
温馨提示?:要多看官方API,英语基础弱的小伙伴,可以直接看代码示例,直接上代码~
铺垫: 1.vue的作者:尤雨溪(华人),前Google员工; 2.vue是构建数据驱动的web应用开发框架; 3.vue是一套用于构建用户界面的渐进式框架;(渐进式:可以在原有的系统上开发,把一两个组件改用vue实现,也可以整个用vue全家桶开发,不会做职责之外的事。) 4.vue被设计为可以自顶向上增量开发逐层应用;( 自顶向上增量开发:先写一个基础页面,把基础的东西写好,再逐一添加功能和效果,由简单到繁琐的过程。) 5.vue的核心只关注视图层; 6.vue框架的核心:数据驱动和组件化; 7.vue不支持IE8及以下版本。
3.1vue框架
3.1.1理解
1.写好HTML模板,声明式地告知vuejs库,数据显示在何处,在vue对象中处理数据,不用做DOM操作(vuejs库会帮我们做哦)即new出来一个Vue实例,传一堆配置参数,就可以控制一片html。
3.1.2名词解释
- 数据驱动:通过控制数据的变化来改变(驱动)DOM,背后使用了观察者模式,靠数据的变化来控制页面的变化。
- 声明式渲染:告知程序(vue框架),在何处渲染什么数据。
- 数据绑定:是通过数据劫持和观察者模式的方式来实现的。
①数据劫持:vue2.x使用Object.defineProperty();,vue3使用的是Proxy。把普通JavaScript对象(json)传入Vue实例作为data选项,Vue将遍历此对象所有的属性,并使用Object.defineProperty()把这些属性全部转为getter/setter。
class MyVue {
constructor(obj) {
this.sourc`e`HtmlStr = document.querySelector(obj.el).innerHTML;
let o = new Observer();
o.addSubsciber((what) => {
this.render();
});
for (let key in obj) {
this["$" + key] = obj[key];
}
for (let key in obj.data) {
Object.defineProperty(this, key, {
set: function(newVal) {
this["_" + key] = newVal;
this.$data[key] = newVal;
o.publish(newVal);
},
get: function() {
return this["_" + key];
}
});
}
this.render();
}
render() {
let newHtmlStr = this.sourceHtmlStr;
for (let key in this.$data) {
newHtmlStr = newHtmlStr.replace(new RegExp("{{" + key + "}}", "g"), this.$data[key]);
}
document.querySelector(this.$el).innerHTML = newHtmlStr;
}
}
class Observer {
constructor() {
this.arr = [];
}
addSubsciber(cb) {
this.arr.push(cb);
}
removeSubscriber(cb) {
let index = this.arr.indexOf(cb);
this.arr.splice(index, 1);
}
publish(what) {
this.arr.forEach(item => {
item(what);
});
}
}
②观察者模式(发布订阅模式): 目的:当属性发生变化时,所有使用该数据的地方跟着变化。(响应式)
let observer = {
arr:[],
addSubscriber:function(fn){
this.arr.push(fn);
},
publish:function(what){
this.arr.forEach(fn=>{
fn(what);
});
}
}
- 组件:页面中的一个个ui部件,写在components文件夹下。
- 页面组件:项目中的一个个页面整体,写在views/pages文件夹下。
- 单页面应用(SPA):single page application,整个项目中只有一个HTML页面(文件),首次加载是,把所有的html、css、js全部加载下来。通过操作dom的删除和创建(添加)来完成页面的切换。
- 单页面文件:single-file components,文件扩展名为 .vue 的 (单文件组件) 。(这点小编还不太清楚,弄懂了及时告诉你们哦~)
四.组件
组件封装的是完整的功能(包括:html、css、js),而函数只封装js(逻辑)。
4.1概念
1.组件是自定义标签,vueJS提供的组件可以让程序员自定义标签,对页面进行模块化。每个标签中包含html、css、js。 2.vue的组件是一个vue对象,vue对象的配置项,在vue组件中可以使用。 注:
- 没有el属性;
- template:HTML模板代码,只能有一个根标签;
- data:必须是个函数;? 组件中的 data 必须是一个函数,且要返回object,只有这样,每个实例(vue组件对象)就可以维护一份被返回对象的独立的拷贝,否则组件复用时,数据相互影响,也就是说,组件的作用域是独立的。
? 简单回答:如果不是函数,那么,复用的组件的data共享同一块内存空间。
一个完整的标签名格式: <标签名 属性名=“属性值" 事件=”函数“>内容</标签名> 根据HTML的标签理解组件,我也是根据标签的格式,来说组件啦~
4.2组件的基本使用(标签名)
4.2.1定义组件
(一)标准版
let 组件变量名= Vue.extend({
template:'<div class="header">{{msg}},我是header组件</div>'
data:function(){
return {
msg:”hi”
}
},
});
(二)简化写法
let 组件变量名={
配置项
};
4.2.2注册组件
- 全局注册component:在任何vue对象里都可以使用。
Vue.component('组件名',组件变量名);
- 局部注册components:只能在当前vue对象(组件)里使用。
new Vue({
el:
components:{
组件名:组件变量名
}
});
4.2.3使用组件
组件就是自定义标签,使用组件就和使用官方标签是一样的。直接写名称就可以。
注意:如果组件定义时变量为驼峰命名,则在使用时,使用羊肉串的方式。双标签和单标签都可以的吆~ <组件名></组件名> <组件名/>
4.2.4组件嵌套
把一个组件的标签写在另外一个组件的template中。 eg:父组件中嵌套了子组件
let myComSon = {
template:"<div>我是son里的div:{{msg}}</div>",
data:function(){
return {
msg:"hi:son"
}
}
};
let myComParent = {
template:`<div>
<p>我是p:{{msg}}</p>
<my-com-son></my-com-son>
</div>`,
data:function(){
return {
msg:"hi"
}
},
components:{
"my-com-son":myComSon
}
};
4.2.5组件编写方式 vs Vue实例的区别
来自小编的福利:小驼峰和大驼峰 小驼峰:除过首字母不大写,其余单词首字母大写; 大驼峰:所有单词首字母大写。
- 组件名不可和HTML官方的标签名同名,组件名如果如果使用小驼峰,那么使用时,用短横线(羊肉串)或者组件名首字母大写;
- 组件没有el选项,只有根实例存在el,组件里使用template定义模板;
- 组件模板(html代码)只能有一个根标签;
- 组件中的data必须是一个函数。实例中不是函数。
4.3组件的属性(标签的属性)
1.使用props来完成组件属性的声明。props是外部给组件传入的数据。而组件的data是组件内部的数据。
4.3.1使用Prop传递静态数据
①在组件内部增加配置项props来声明组件里的属性。props里面可以声明多个属性。所以是一个数组。
let myComParent = {
props:["name","sex"],
template:`<div>
<p>我是p:{{msg}}</p>
<p>人的信息:</p>
<p>姓名:{{name}}</p>
<p>性别:{{sex}}</p>
</div>`,
data:function(){
return {
msg:"hi"
}
}
};
②使用组件时,给属性传入数据:
<my-com-parent name="张三疯他哥" sex="男"></my-com-parent>
③总结 封装组件和封装函数进行类比: ●在组件内部用props声明的属性,相当于封装函数时声明的形参; ●使用组件时,相当于调用函数,传递实参。
4.3.2使用Prop传递动态数据
即是给组件的属性v-bind(绑定动态数据)
<my-com-parent v-bind:name="name" sex="男"></my-com-parent>
如果想把对象的所有属性作为prop进行传递,可以使用不带任何参数的v-bind(即用v-bind而不是v-bind:prop-name).
todo: {
text: 'Learn Vue',
isComplete: false
}
<todo-item v-bind="todo"></todo-item>
<todo-item
v-bind:text="todo.text"
v-bind:is-complete="todo.isComplete"
></todo-item>
奇葩情况: 在JavaScript中对象和数组是通过引用传入的(传的是地址),所以对于一个数组或对象类型的prop来说,在子组件中改变这个对象或数组苯磺酸呢将会影响到父组件的状态(data),相当于函数的形参是引用类型。
4.3.3 Prop验证
vueJS提供了对属性类型的验证、属性默认值、是否必须等。
这时props不能使用数组,而需要使用对象。
props:{
"name":{
type:String,
required:true
},
"sex":[String,Number],
"age":{
type:Number,
default:10
},
"isadult":Boolean
},
4.3.4单向数据流
Prop 是单向绑定的:当父组件的属性(数据)变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。 另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。
4.4.组件的事件
4.4.1绑定事件
- HTML(标签)里的绑定方式:v-on
- JS(Vue)里绑定方式: vue对象.$on(“事件名”)
4.4.2触发事件
vue对象.$emit(“事件名”,参数);
Vue.component('button-counter',{
template: "<input type='button' v-on:click='incrementCounter' v-model='counter' />",
data:function(){
return {
counter:0
}
},
methods:{
incrementCounter:function(){
this.counter += 1
this.$emit('increment')
}
}
});
<div id="app1">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
var app1 = new Vue({
el: '#app1',
data:{
total:0
},
methods:{
incrementTotal:function(){
this.total += 1;
}
}
});
4.5组件的内容(插槽)
- 组件的内容就是标签的innerHTML。vueJS里使用**Slot(插槽)**分发内容。
- 将父组件的内容(DOM)放到子组件指定的位置叫作内容分发。
- 分类
4.5.1单个插槽
let person = {
template:`<div>
<hr/>
<p>我是上p</p>
<slot></slot>
<p>我时下p</p>
<hr/>
</div>`
};
<div id="app">
<person>
<div>我是div</div>
</person>
</div>
new Vue({
el:"#app",
components:{
person
}
});
4.5.2具名插槽
如果父级给子级传来好多DOM(HTML元素),而且需要把不同的DOM放在子组件不同位置时,需要给slot起名字。利用slot元素的特殊属性name来配置如何来分发内容。
<slot name="插槽名"></slot>
let person = {
template:`<div>
<hr/>
<p>我是上p</p>
<slot name="s1"></slot>
<p>我是中p</p>
<slot name="s2"></slot>
<p>我是下p</p>
<hr/>
</div>`
};
<div id="app">
<person>
<div slot="s1">我是div1</div>
<div slot="s2">我是div2</div>
</person>
</div>
new Vue({
el:"#app",
components:{
person
}
});
4.5.3编译作用域
父组件模板的内容在父组件作用域内(父组件对应的对象的作用域)编译;子组件模板的内容在子组件作用域内编译。
let person = {
template:`<div>
<hr/>
<p>我是上p:{{t}}</p>
<p>我是下p</p>
<hr/>
</div>`,
data(){
return{
t:"我是子组件的数据"
}
}
};
<div id="app">
<input :value="msg" />
<person v-show="s">
<p>{{msg}}</p>
<div>我是div1:{{msg}}</div>
</person>
</div>
new Vue({
el:"#app",
data:{
msg:"hi",
s:true
},
components:{
person
}
});
扩展:有余力的小可爱阔以自行研究一下作用域与插槽!
4.6组件(间)的通信
vue组件之间的通信(传递数据)是必然的,依据vue组件之间的关系(父子,兄弟,或者无关组件)会有不同的做法:
- 父子组件:props /ref/s $emit
- 父子、隔代、兄弟组件通信 :EventBus $emit / $on
- 集中管理,适用于所有场景:$root
- 适用于所有场景:Vuex,路由
下面为大家一一讲解,路由,Vuex后续讲道router、Vuex详讲解。
4.6.1父子组件
父->子:props,refs,也叫正向传值; 子->父:事件,逆向传值。
props传值:就是上面所提到的prop动态传值。 ①子组件
<template>
<div>
<!-- 使用 -->
homezi--{{title}}---{{num}}--{{sex}}
</div>
</template>
<script>
export default {
// 子组件设置好了接收
props:["title","num",'sex']
}
</script>
②父组件
<template>
<div>
home
<!-- 在子组件被调用的地方 进行传递 -->
<Homezi title="我是title" num="我是num" sex="我是sex"/>
</div>
</template>
<script>
import Homezi from "./homezi.vue"
export default {
components:{
Homezi
}
}
</script>
- refs传值: **用标签的方式使用组件,实际就是创建了组件对象。**只要拿到组件对象,那么组件对象中的methods就可以使用。refs是vue中获取dom的一种方式,dom也就是标签,标签就是组件对象。即拿到了dom,就相当于拿到了组件对象。(这句话细细品味幺,开动你们的小脑筋)
如果某个元素使用ref属性,那么,在vue对象里,就能用this.$refs 访问。可以认为是给元素增加了个id属性,在vue里就可以操作该dom了。
格式:
<p ref = "pId"> {{msg}}</p>
methods:{
testf:function(){
this.$refs.pId.innerHTML = "hi";
}
}
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="app">
<input type="text" :value="str" ref="txt"> <input type="button" value="测试" @click="fn">
<parent ref="par"></parent>
</div>
<script src="vue.js"></script>
<script>
let son = {
template: ` <div>
<p>我是子组件</p>
</div>`
}
let parent = {
template: `
<div>
<p>我是父组件</p>
<p>{{str1}}</p>
<son></son>
</div>`,
data: function() {
return {
str1: "hi,我是str1"
}
},
components: {
son
}
};
let vm = new Vue({
el: ".app",
components: {
parent: parent
},
data: {
str: "hi"
},
methods: {
fn() {
this.$refs.txt.type = "button";
this.$refs.par.str1 = "哈哈哈";
}
}
})
</script>
</body>
</html>
4.6.2兄弟组件
4.6.1.1事件总线events-bus
1.vue-bus实质就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信。它是实现非父子组件通信的一种解决方案。 2.步骤:假如B组件给A组件传值,则B组件触发,A组件绑定事件
①单独new一个Vue空对象: let bus= new Vue(); ②在组件A里,绑定一个自定义事件(相当于定义了一个自定义事件): bus.$on(‘eclick’,target => { console.log(target) })
③在组件B里,触发事件 bus.$emit(‘eclick’,“b传给a的”);
3.示例
let bus = new Vue();
let myCom1 = {
template:`
<div>
<hr>
组件com1
<hr>
</div>
`,
created(){
bus.$on("eclick",(target)=>{
console.log(target);
});
}
}
let myCom2 = {
template:`
<div>
<input type="button" value=" 传 " @click="fn" />
</div>
`,
methods:{
fn(){
bus.$emit("eclick","hello");
}
}
}
Vue.component("my-com1",myCom1);
Vue.component("my-com2",myCom2);
new Vue({
el:"#app"
});
4.6.1.2集中管理($root)
把数据存到根实例的data选项,其他组件直接修改或者使用。 1.定义:
new Vue({
data:{a:1}
})
2.使用
this
this.$root
this.xx
this.$root.a
4.6.3动态组件
有的时候,在不同组件之间进行动态切换是非常有用的。即页面的某个位置要显示的组件是不确定的,是会变化的。
<component :is="组件名变量">
示例:
<div id="app">
<span @click="show(0)">娱乐</span>|<span @click="show(1)">八卦</span>|<span @click="show(2)">体育</span>
<div>
<component :is="currCom"></component>
</div>
</div>
let yuLe = {
template:"<div>娱乐新闻</div>"
}
let eightGua = {
template:"<div>八卦新闻</div>"
}
let sports = {
template:"<div>体育新闻</div>"
}
new Vue({
el:"#app",
data:{
currCom:"yuLe",
coms:["yuLe","eightGua","sports"]
},
methods:{
show(index){
this.currCom = this.coms[index];
}
},
components:{
yuLe,eightGua,sports
}
});
今天先为大家分享到这,想听后续,可以点击关注?,blue胖胖才有动力持续为您更新~
|