脚本宝典收集整理的这篇文章主要介绍了vue笔记详解,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
我相信每个人学习Vue的目的是各部相同的。
可能你的公司正要将原有的项目使用Vue进行重构。
也可能是你的公司新项目决定使用Vue的技术栈。
当然,如果你现在正在换工作,你会发现招聘前端的需求中,10个有8个都对Vue有或多或少的要求。
Vue (读音 /vjuː/,类似于 view),不要读错。
Vue是一个渐进式的框架,什么是渐进式的呢?
Vue有很多特点和Web开发中常见的高级功能
学习Vuejs的前提?
使用一个框架,我们第一步要做什么呢?安装下载它
安装Vue的方式有很多:
方式一:直接CDN引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
方式二:下载和引入
开发环境 https://vuejs.org/js/vue.js
生产环境 https://vuejs.org/js/vue.min.js
我们来做我们的第一个Vue程序,体验一下Vue的响应式
代码做了什么事情?
我们来阅读JavaScript代码,会发现创建了一个Vue对象。
创建Vue对象的时候,传入了一些options:{}
浏览器执行代码的流程:
并且,目前我们的代码是可以做到响应式的。
<div id="app">
<p v-if="seen">现在可以看到我了</p>
<a :href="url">点击我</a>
</div>
<script tyPE="text/javascript">
VAR app = new Vue({
el: "#app",
data: {
seen: false,
url: "https://learning.dcloud.io/#/?vid=6"
}
});
</script>
什么是MVVM呢?
我们直接来看Vue的MVVM
你会发现,我们在创建Vue实例的时候,传入了一个对象options。
这个options中可以包含哪些选项呢?
目前掌握这些选项:
如何将data中的文本数据,插入到HTML中呢?
我们可以像下面这样来使用,并且数据是响应式的
但是,在某些情况下,我们可能不希望界面随意的跟随改变
v-once:
该指令后面不需要跟任何表达式(比如之前的v-for后面是由跟表达式的)
该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变。
代码如下:
<div id="app">
<h2>{{message}}</h2>
<h2 v-once>{{message}}</h2>//只展现一次message的数据,当后面的message发生改变的时候,这个message不会发生改变。
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
}
})
</script>
某些情况下,我们从服务器请求到的数据本身就是一个HTML代码
如果我们希望解析出HTML展示
可以使用v-html指令
该指令后面往往会跟上一个string类型
会将string的html解析出来并且进行渲染
<div id="app">
<h2>{{url}}</h2> //输出:<a href="https://www.bilibili.COM/video/BV15741177Eh?p=14&spm_id_From=pageDriver">b站一下<a>
<h2 v-html="url"></h2> //输出:b站一下
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
url: '<a href="https://www.bilibili.com/video/BV15741177Eh?p=14&spm_id_from=pageDriver">b站一下<a> '
}
})
</script>
v-text作用和Mustache比较相似:都是用于将数据显示在界面中
v-text通常情况下,接受一个string类型
<div id="app">
<h2>{{message}}</h2> //你好啊!!!
<h2 v-text="message"></h2> //你好啊!!!
<!-- message会覆盖掉h2里面的内容 -->
<!-- 、//如果只有文本的话可以用<v-text></v-text> -->
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
}
})
</script>
v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。
比如下面的代码:
在某些情况下,我们浏览器可能会直接显然出未编译的Mustache标签。
cloak: 斗篷
前面我们学习的指令主要作用是将值插入到我们模板的内容当中。
但是,除了内容需要动态来决定外,某些属性我们也希望动态来绑定。
这个时候,我们可以使用v-bind指令:
下面,我们就具体来学习v-bind的使用。
v-bind用于绑定一个或多个属性值,或者向另一个组件传递props值(这个学到组件时再介绍)
在开发中,有哪些属性需要动态进行绑定呢?
v-bind有一个对应的语法糖,也就是简写方式
比如通过Vue实例中的data绑定元素的src和href,代码如下:
<div id="app">
<img v-bind:src="imgURL" alt="">
<img :src="imgURL" alt="">
<!-- 两者效果一样 -->
<!--v-bind的语法糖写法 v-bind---》: -->
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
imgURL: "../../images/back-2.jpg"
}
})
</script>
很多时候,我们希望动态的来切换class,比如:
绑定class有两种方式:
绑定方式:对象语法
对象语法有下面这些用法::
用法一:直接通过{}绑定一个类
<h2 :class="{'active': isActive}">Hello World</h2>
用法二:也可以通过判断,传入多个值
<h2 :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:如果isActive和isLine都为true,那么会有title/active/line三个类
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>
案例:
<div id="app">
<!-- 固定的class和动态的的class可以共存,不会相互覆盖 -->
<h2 class="title" :class="{active: isActive,line:isLine}">{{message}}</h2>
<h2 class="title" :class="getClass()">{{message}}</h2>
<!-- 调用函数的时候要加小括号,下面的按钮中的那个可以省略 -->
<button @click="BTnClick">切换颜色</button>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
isActive: true,
isLine: true
},
methods: {
btnClick: function() {
this.isActive = !this.isActive
},
getClass: function() {
return {
active: this.isActive,
line: this.isLine
// 要用到本作用域中的变量的时候记住加this.
}
}
}
})
</script>
数组语法有下面这些用法:
用法一:直接通过{}绑定一个类
<h2 :class="['active']">Hello World</h2>
用法二:也可以传入多个值
<h2 :class=“[‘active’, 'line']">Hello World</h2>
用法三:和普通的类同时存在,并不冲突
注:会有title/active/line三个类
<h2 class="title" :class=“[‘active’, 'line']">Hello World</h2>
用法四:如果过于复杂,可以放在一个methods或者computed中
注:classes是一个计算属性
<h2 class="title" :class="classes">Hello World</h2>
我们可以利用v-bind:style来绑定一些CSS内联样式。
在写CSS属性名的时候,比如font-size
绑定class有两种方式:
:style="{color: currentColor, fontSize: fontSize + 'px'}"
style后面跟的是一个对象类型
对象的key是CSS属性名称
对象的value是具体赋的值,值可以来自于data中的属性
案例:
<div id="app">
<!-- 50px必须加上一个单引号,否则当成以后个变量解析的 -->
<h2 :style="{fontSize: '50px'}">{{message}}</h2>
<!-- finalsize直接当成一个变量使用了 -->
<h2 :style="{fontSize: finalsize}">{{message}}</h2>
<h2 :style="{fontSize: finalsize1+'px',color:finalcolor}">{{message}}</h2>
<h2 :style="getStyle()">{{message}}</h2>
<!-- 是方法,记住一定要加() -->
<p :style="{'fontSize': finalsize,color:finalcolor}">{{fullName}}</p>
<!-- 使用computed不需要加() -->
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
finalsize: '100px',
finalsize1: 100,
finalcolor: 'red',
FirstName: "Lebron",
lastName: "James"
},
// 计算属性
computed: {
fullName() {
return this.firstName + " " + this.lastName
}
},
//方法
methods: {
getStyle() {
return {
fontSize: this.finalsize1 + 'px',
color: this.finalcolor
}
}
}
})
</script>
<div v-bind:style="[baseStyles, overridingStyles]"></div>
style后面跟的是一个数组类型
多个值以,分割即可
我们知道,在模板中可以直接通过插值语法显示一些data中的数据。
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示
我们可以将上面的代码换成计算属性:
OK,我们发现计算属性是写在实例的computed选项中的。
计算属性中也可以进行一些更加复杂的操作,比如下面的例子
<div id="app">
<h2>总价格:{{totalPrice}}</h2>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
Books: [{
id: 110,
name: '代码大全',
prise: 119
}, {
id: 111,
name: '代码大全',
prise: 112
}, {
id: 112,
name: '代码大全',
prise: 101
}, {
id: 113,
name: '代码大全',
prise: 109
}]
},
computed: {
totalPrice: function() {
let result = 0;
for (let i = 0; i < this.books.length; i++) {
result += this.books[i].prise;
}
return result;
}
}
})
</script>
<h2>{{counter}}</h2>
<button v-on:click='increment(10)'>+1</button>
<button @click='decrement'>-1</button>
//定义各种各样的方法
methods: {
increment(count) {
console.LOG(count);
this.counter++;
},
decrement() {
this.counter--;
}
}
当通过methods中定义方法,以供@click调用时,需要注意参数问题:
情况一:如果该方法不需要额外参数,那么方法后的()可以不添加。
情况二:如果需要同时传入某个参数,同时需要event时,可以通过$event传入事件。
在某些情况下,我们拿到event的目的可能是进行一些事件处理。
Vue提供了修饰符来帮助我们方便的处理一些事件:
<!--停止冒泡-- >
<button @click.stop= "doThis">< /button>
<!--阻止默认行为-->
<button @click.prevent="doThis">< /button>
<!--阻止默认行为,没有表达式-->
<form @submit.prevent></ form>
< !--串联修饰符-->
<button @click.stop.prevent="doThis"></button>
<!--键修饰符,键别名-->
<input @keyup.enter="onEnter">
<!--键修饰符,键代码-->
<input @keyup.13="onEnter">
<!--点击回调只会触发-次-- >
<button @click.once="doThis"></button>
这三个指令与JavaScript的条件语句if、else、else if类似。
Vue的条件指令可以根据表达式的值在DOM中渲染或销毁元素或组件
v-if的原理:
案例演示:
<div id="app">
<span v-if="username">
<label for="one">用户账号:</label>
<input type="text" id="one" placeholder="填写用户账号" key="one">
</span>
<span v-else>
<label for="two">用户邮箱:</label>
<input type="text" id="two" placeholder="填写用户邮箱" key="two">
</span>
<button @click="username=!username">切换类型</button>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
username: true
}
})
</script>
案例小问题:
小问题:
问题解答:
解决方案:
v-show的用法和v-if非常相似,也用于决定一个元素是否渲染:
v-if和v-show****对比
v-if和v-show都可以决定一个元素是否渲染,那么开发中我们如何选择呢?
开发中如何选择呢?
<div id="app">
<h2 v-if="isShow" id="one">{{message}}</h2>
<h2 v-show="isShow" id="two">{{message}}</h2>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
isShow: true
}
})
</script>
当我们有一组数据需要进行渲染时,我们就可以使用v-for来完成。
我们来看一个简单的案例:
如果在遍历的过程中不需要使用索引值
如果在遍历的过程中,我们需要拿到元素在数组中的索引值呢?
<div id="app">
<ul>
<li v-for="(item,index) of name">{{index+1}}.{{item}}</li>
</ul>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
name: ['fhkjsd', 'aDFga', 'sdfasd', 'asdfgsd']
}
})
</script>
遍历对象
<div id="app">
<!-- 1.在遍历对象的过程中,如果只是获取一个值,那么获取到的是 value -->
<ul>
<li v-for="item of foo">{{item}}</li>
</ul>
<!-- 2.获取key和value 格式:(value,key) -->
<ul>
<li v-for="(item,key) of foo">{{key}}:{{item}}</li>
</ul>
<!-- 3.获取key,value和索引 格式:(value,key,index) -->
<ul>
<li v-for="(item,key,index) of foo">{{index}}-{{key}}:{{item}}</li>
</ul>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
foo: {
name: 'why', //name:是key,why:是value。
age: '21',
height: '1.78'
}
}
})
</script>
官方推荐我们在使用v-for时,给对应的元素或组件添加上一个:key属性。
为什么需要这个key属性呢(了解)?
当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点
所以我们需要使用key来给每个节点做一个唯一标识
所以一句话,key的作用主要是为了高效的更新虚拟DOM。
响应式的:
<div id="app">
<ul>
<li v-for="item of letters">{{item}}</li>
</ul>
<button @click="btnClick">点击</button>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
letters: ['a', 'b', 'c', 'd']
},
methods: {
btnClick() {
//1.push的方法;在最后面添加元素。
// this.letters.push('aaa')
//括号中可以跟多个,一次遍历
//2.pop(); 删除数数组中最后一个元素;
// this.letters.pop();
//3.shift(); 删除数组中的第一个元素;
// this.letters.shift();
//4.unshift(); 在数组的最前面添加元素;
// this.letters.unshift('aaaa');
//括号中可以跟多个,一次遍历
//5.splice();
//splice()的作用;删除元素,插入元素,替换元素
//splice(start); 从第几个元素开始 第一参数都一样
// this.letters.splice(start);
//如果是删除元素,第二个参数传入的是你要删除几个元素(如果没有传值就删除后面所有的元素)
// this.letters.splice(start,(要删除元素的个数));
//替换元素:第二个参数,传入0,并且后面跟上要插入的元素。都好分隔;
// this.letters.splice(start,(要替换元素的个数),(要替换的元素,替换几个写几个));this.letters.splice(1,3,'b','d','d')
//插入元素:
// this.letters.splice(1, 0, 'x', 'y', 'z')
//6.sort():排序
// this.letters.sort()
//7.reverse():反转元素;
this.letters.reverse()
//注意:通过索引直接修改数组中的元素 这不是响应式的
// this.letters[0] = 'aaaaa'
}
}
})
</script>
表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。
Vue中使用v-model指令来实现表单元素和数据的双向绑定。
案例的解析:
当然,我们也可以将v-model用于textarea元素
<div id="app">
<!-- 双向绑定 -->
<input type="text" v-model=" message ">
<!-- 单向绑定 获得data中的message的值 -->
<input type="text" :value=" message ">
<!-- 单向绑定 input:获取输入框中的内容事件,输入的值后改变message-->
<input type="text" v-on:input="valueChange">
<input type="text" :value=" message " @input="message=$event.target.value">
<h2>{{message}}</h2>
</div>
<script text="javascript ">
let app = new Vue({
el: "#app ",
data: {
message: "你好啊!!! ",
},
methods: {
valueChange(event) {
this.message = event.target.value;
}
}
})
</script>
v-model其实是一个语法糖,它的背后本质上是包含两个操作:
也就是说下面的代码:等同于下面的代码:
<input type="text" v-model="message">
等同于
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
当存在多个单选框时
复选框分为两种情况:单个勾选框和多个勾选框
单个勾选框:
多个复选框:
案例:
<div id="app">
<label for="agree">
<input type="checkbox" id="agree" v-model="isAgree">喜欢cyl
</label>
<h2>你的选择是:{{isAgree}}</h2>
<button :disabled="!isAgree">下一步</button>
<br>
<br> <br>
<input type="checkbox" value="篮球" v-model="hoddy">篮球
<input type="checkbox" value="足球" v-model="hoddy">足球
<input type="checkbox" value="乒乓球" v-model="hoddy">乒乓球
<input type="checkbox" value="羽毛球" v-model="hoddy">羽毛球
<h2>你的爱好是:{{hoddy}}</h2>
<br>
<br>
<br>
<label v-for="item of origilhoddy" :for="item">
<input type="checkbox" :value="item" :id="item" v-model="hoddy">{{item}}
</label>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
isAgree: true, //单选框对应的是布尔值
hoddy: [], //多选框对应的是数组
origilhoddy: ['篮球', '足球', '乒乓球', '橄榄球', '羽毛球']
}
})
</script>
和checkbox一样,select也分单选和多选两种情况。
单选:只能选中一个值。
多选:可以选中多个值。
<div id="app">
<!-- 选择一个值 -->
<select v-model="mySelect">
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
</select>
<p>你喜欢的水果:{{mySelect}}</p>
<br>
<select v-model="mySelects" multiple>
<option value="apple">苹果</option>
<option value="banana">香蕉</option>
<option value="orange">橘子</option>
</select>
<p>你喜欢的水果:{{mySelects}}</p>
</div>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
mySelect: 'apple',
mySelects: []
}
})
</script>
初看Vue官方值绑定的时候,我很疑惑:what the hell is that?
但是仔细阅读之后,发现很简单,就是动态的给value赋值而已:
这不就是v-bind在input中的应用吗?搞的我看了很久,搞不清他想将什么。
这里不再给出对应的代码,因为会用v-bind,就会值绑定的应用了。
lazy修饰符:
number修饰符:
trim修饰符:
<div id="app">
<input type="text" v-model.lazy="message">
<p>当前内容:{{message}}</p>
年龄:<input type="number" v-model.number="age">
<p>年龄:{{age}} 类型{{typeof age}}</p>
<input type="text" v-model.trim="message">
<p>当前内容:----{{message}}------</p>
</div>
人面对复杂问题的处理方式:
组件化也是类似的思想:
我们将一个完整的页面分成很多个组件。
每个组件都用于实现页面的一个功能块。
而每一个组件又可以进行细分。
组件化思想的应用:
所以,组件是Vue开发中,非常重要的一个篇章,要认真学习。
组件的使用分成三个步骤:
我们来看看通过代码如何注册组件
查看运行结果:
这里的步骤都代表什么含义呢?
1.Vue.extend():
2.Vue.component():
3.组件必须挂载在某个Vue实例下,否则它不会生效。(见下页)
当我们通过调用Vue.component()注册组件时,组件的注册是全局的
如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jpDFBYUF-1638328245757)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917103355282.png)]
在前面我们看到了组件树:
我们来看通过代码如何组成的这种层级关系:
父子组件错误用法:以子标签的形式在Vue实例中使用
在上面注册组件的方式,可能会有些繁琐。
语法糖注册全局组件和局部组件:
刚才,我们通过语法糖简化了Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块写法。
如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。
Vue提供了两种方案来定义HTML模块内容:
组件是一个单独功能模块的封装:
组件中的数据是保存在哪里呢?顶层的Vue实例中吗?
我们发现不能访问,而且即使可以访问,如果将所有的数据都放在Vue实例中,Vue实例就会变的非常臃肿。
结论:Vue组件应该有自己保存数据的地方。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imbA9jQz-1638328245767)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917113741987.png)]
在上一个小节中,我们提到了子组件是不能引用父组件或者Vue实例的数据的。
但是,在开发中,往往一些数据确实需要从上层传递到下层:
如何进行父子组件间的通信呢?Vue官方提到
通过props向子组件传递数据
通过事件向父组件发送消息
在下面的代码中,我直接将Vue实例当做父组件,并且其中包含子组件来简化代码。
真实的开发中,Vue实例和子组件的通信和父组件和子组件的通信过程是一样的。
在组件中,使用选项props来声明需要从父级接收到的数据。
props的值有两种方式:
我们先来看一个最简单的props传递:
在前面,我们的props选项是使用一个数组。
我们说过,除了数组之外,我们也可以使用对象,当需要对props****进行类型等验证时,就需要对象写法了。
验证都支持哪些数据类型呢?
当我们有自定义构造函数时,验证也支持自定义的类型
3.子集向父级传递
props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。
我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成。
什么时候需要自定义事件呢?
自定义事件的流程:
我们来看一个简单的例子:
有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问跟组件。
我们先来看下$children的访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UxfDNeJW-1638328245776)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917145920562.png)]
$children的缺陷:
$refs的使用:
如果我们想在子组件中直接访问父组件,可以通过$parent
注意事项:
刚才我们讨论的都是父子组件间的通信,那如果是非父子关系呢?
在Vue1.x的时候,可以通过 d i s p a t c h 和 dispatch和 dispatch和broadcast完成
在Vue2.x中,有一种方案是通过中央事件总线,也就是一个中介来完成。
在真正学习插槽之前,我们需要先理解一个概念:编译作用域。
官方对于编译的作用域解析比较简单,我们自己来通过一个例子来理解这个概念:
我们来考虑下面的代码是否最终是可以渲染出来的:
答案:最终可以渲染出来,也就是使用的是Vue实例的属性。
为什么呢?
slot翻译为插槽:
组件的插槽:
例子:移动网站中的导航栏。
如何去封装这类的组件呢?
如何封装合适呢?抽取共性,保留不同。
这就是为什么我们要学习组件中的插槽slot的原因。
了解了为什么用slot,我们再来谈谈如何使用slot?
我们通过一个简单的例子,来给子组件定义一个插槽:
当子组件的功能复杂时,子组件的插槽可能并非是一个。
如何使用具名插槽呢?
我们来给出一个案例:
<div id="app">
<cpn><button slot="middle">按钮</button></cpn>
<cpn><span slot="left">哈哈哈哈</span></cpn>
</div>
<template id="cpn">
<div>
<slot name="left"><span>左边</span></slot>
<slot name="middle"><span>中间的</span></slot>
<slot name="right"><span>右边</span></slot>
<slot><button>按钮替换</button></slot>
</div>
</template>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
},
components: {
cpn: {
template: '#cpn'
}
}
})
</script>
作用域插槽是slot一个比较难理解的点,而且官方文档说的又有点不清晰。
这里,我们用一句话对其做一个总结,然后我们在后续的案例中来体会:
我们先提一个需求:
我们来看看子组件的定义:
在父组件使用我们的子组件时,从子组件中拿到数据:
我们通过获取到slotone属性
在通过slotone.data就可以获取到刚才我们传入的data了
<div id="app">
<cpn></cpn>
<cpn>
<template slot-scope="slotone">
<div>
<span v-for="item of slotone.data">{{item}}- </span>
</div>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<!-- data:这是自己起的名字 -->
<slot :data="pLanguages">
<ul>
<li v-for="item of pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script text="javascript">
let app = new Vue({
el: "#app",
data: {
message: "你好啊!!!",
},
components: {
cpn: {
template: '#cpn',
data() {
return {
pLanguages: ['大熊', '熊大', '熊二', '光头强']
}
}
}
}
})
</script>
如果你只是简单写几个Vue的Demo程序, 那么你不需要Vue CLI.
如果你在开发大型项目, 那么你需要, 并且必然需要使用Vue CLI
CLI是什么意思?
安装NodeJS
检测安装的版本
什么是NPM呢**?**
注:cnpm安装
由于国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像。
你可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:npm install -g cnpm --registry=https://registry.npm.taobao.org
这样就可以使用 cnpm 命令来安装模块了:cnpm install [name]
注:具体的安装可以分为命令行安装和图像化界面安装,看哪个适合,这一部分初学者最好是自己先摸索如何安装和使用,如果自己没有配置或者安装好,找已经走过本阶段的学长学姐或则朋友指导如何安装。
流程:
说起路由你想起了什么?
额, 啥玩意? 没听懂
路由中有一个非常重要的概念叫路由表.
早期的网站开发整个HTML页面是由服务器来渲染的.
但是, 一个网站, 这么多页面服务器如何处理呢?
上面的这种操作, 就是后端路由.
后端路由的缺点:
前后端分离阶段:
单页面富应用阶段:
前端路由的核心是什么呢?
history接口是HTML5新增的, 它有五种模式改变URL而不刷新页面.
history.pushState()
目前前端流行的三大框架, 都有自己的路由实现:
当然, 我们的重点是vue-router
vue-router是基于路由和组件的
后续开发中我们主要是通过工程化的方式进行开发的.
使用vue-router的步骤:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mSbM93D-1638328245789)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917215258160.png)]
@H_703_3406@
: 该标签是一个vue-router中已经内置的组件, 它会被渲染成一个标签.(跳转路由)
: 该标签会根据当前的路径, 动态渲染出不同的组件.
网页的其他内容, 比如顶部的标题/导航, 或者底部的一些版权信息等会和处于同一个等级.
在路由切换时, 切换的是挂载的组件, 其他内容不会发生改变.
我们这里还有一个不太好的实现:
如何可以让路径默认跳到到首页, 并且渲染首页组件呢?
我们前面说过改变路径的方式有两种:
如果希望使用HTML5的history模式, 非常简单, 进行如下配置即可:
效果如下图:
在前面的中, 我们只是使用了一个属性: to, 用于指定跳转的路径.
还有一些其他属性:
该class具体的名称也可以通过router实例的属性进行修改
nexact-active-class
类似于active-class, 只是在精准匹配下才会出现的class.
后面看到嵌套路由时, 我们再看下这个属性.
有时候, 页面的跳转可能需要执行对应的JavaScript代码, 这个时候, 就可以使用第二种跳转方式了
比如, 我们将代码修改如下:
@H_354_3607@
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F7ZDJpfR-1638328245807)(https://gitee.com/hzg-sss/typora-picture/raw/master/img/image-20210917222234793.png)]
官方给出了解释:
官方在说什么呢?
路由懒加载做了什么?
const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};=
const About = resolve => require(['../components/About.vue'], resolve);
const Home = () => import('../components/Home.vue')
嵌套路由是一个很常见的功能
路径和组件的关系如下:
1.定义两个组件
2.router中路由嵌套
3.实际页面中跳转路由
4.效果图;
第一步: 创建新的组件Profile.vue
第二步: 配置路由映射
第三步: 添加跳转的
params的类型:
query的类型:
如何使用它们呢? 也有两种方式: 的方式和JavaScript代码方式
获取参数通过$route对象获取的.
通过$route获取传递的信息如下:
我们来考虑一个需求: 在一个SPA应用中, 如何改变网页的标题呢?
普通的修改方式:
有没有更好的办法呢? 使用导航守卫即可.
什么是导航守卫?(重点)
我们可以利用beforeEach来完成标题的修改.
导航钩子的三个参数解析:
补充一:如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数.
补充二: 上面我们使用的导航守卫, 被称之为全局守卫.
更多内容, 可以查看官网进行学习:
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:
官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
状态管理到底是什么?
等等,如果是这样的话,为什么官方还要专门出一个插件Vuex呢?难道我们不能自己封装一个对象来管理吗?
但是,有什么状态时需要我们在多个组件间共享的呢?
OK,从理论上理解了状态管理之后,让我们从实际的代码再来看看状态管理。
我们先来看看单界面的状态管理吧.
我们知道,要在单个组件中进行状态管理是一件非常简单的事情
这图片中的三种东西,怎么理解呢?
在这个案例中,我们有木有状态需要管理呢?没错,就是个数counter。
counter需要某种方式被记录下来,也就是我们的State。
counter目前的值需要被显示在界面中,也就是我们的View部分。
界面发生某些操作时(我们这里是用户的点击,也可以是用户的input),需要去更新状态,也就是我们的Actions
这不就是上面1.3的流程图了吗?
Vue已经帮我们做好了单个界面的状态管理,但是如果是多个界面呢?
也就是说对于某些状态(状态1/状态2/状态3)来说只属于我们某一个试图,但是也有一些状态(状态a/状态b/状态c)属于多个试图共同想要维护的
全局单例模式(大管家)
我们还是简单的实现一个计数器的案例
首先,我们需要在某个地方存放我们的Vuex代码:
好的,这就是使用Vuex最简单的方式了。
我们来对使用步骤,做一个简单的小节:
注意事项:
Vuex有几个比较核心的概念:
我们对它进行一一介绍.
Vuex提出使用单一状态树, 什么是单一状态树呢?
但是,它是什么呢?我们来看一个生活中的例子。
这个和我们在应用开发中比较类似:
有时候,我们需要从store中获取一些state变异后的状态,比如下面的Store中:
我们可以在Store中定义getters
Vuex的store状态的更新唯一方式:提交Mutation
Mutation主要包括两部分:
mutation的定义方式:
mutations:{
increment(state){
state.count++
}
}
increment: function(){
this.$store.commit('increment')
}
在通过mutation更新数据的时候, 有可能我们希望携带一些额外的参数
Mutation中的代码:
上面的通过commit进行提交是一种普通的方式
Vue还提供了另外一种风格, 它是一个包含type属性的对象
this.$store.commit({
type:'changeCount',
count:100
})
changeCount(State,payload){
state.count = payload.count
}
Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.
这就要求我们必须遵守一些Vuex对应的规则:
我们来看一个例子:
如何才能让它改变呢?
我们来考虑下面的问题:
如何避免上述的问题呢?
具体怎么做呢?
通常情况下, Vuex要求我们Mutation中的方法必须是同步方法.
比如我们之前的代码, 当执行更新时, devtools中会有如下信息: 图1
但是, 如果Vuex中的代码, 我们使用了异步函数: 图2
你会发现State中的info数据一直没有被改变, 因为他无法追踪到.
So, 通常情况下,不要再mutation中进行异步的操作
我们强调, 不要再Mutation中进行异步操作.
Action的基本使用代码如下:
context是什么?
这样的代码是否多此一举呢?
在Vue组件中, 如果我们调用action中的方法, 那么就需要使用dispatch
同样的, 也是支持传递payload
前面我们学习ES6语法的时候说过, Promise经常用于异步操作.
OK, 我们来看下面的代码:
Module是模块的意思, 为什么在Vuex中我们要使用模块呢?
我们按照什么样的方式来组织模块呢?
上面的代码中, 我们已经有了整体的组织结构, 下面我们来看看具体的局部模块中的代码如何书写.
注意:
actions的写法呢? 接收一个context参数对象
如果getters中也需要使用全局的状态, 可以接受更多的参数
Vue中发送网络请求有非常多的方式, 那么, 在开发中, 如何选择呢?
为什么不用它呢?
选择二: 在前面的学习中, 我们经常会使用jQuery-Ajax
为什么不选择它呢?
选择三: 官方在Vue1.x的时候, 推出了Vue-resource.
为什么不选择它呢?
选择四: 在说明不再继续更新和维护vue-resource的同时, 作者还推荐了一个框架: axios为什么不用它呢?
n为什么选择axios? 作者推荐和功能特点、
n功能特点
请求地址
请求类型
请根路径
请求前的数据处理
请求后的数据处理
自定义的请求头
URL查询对象
查询对象序列化函数
request body
超时设置s
跨域是否带Token
自定义请求处理
身份验证信息
响应的数据格式 JSON / blob /document /arraybuffer / text / stream
axios封装
axios提供了拦截器,用于我们在发送每次请求或者得到相应后,进行对应的处理。
如何使用拦截器呢?
请求拦截中错误拦截较少,通常都是配置相关的拦截
可能的错误比如请求超时,可以将页面跳转到一个错误页面中。
4.3.拦截器中都做了什么?
<script text="javascript">
const nums = [10, 20, 30, 40, 50, 91, 73, 50]
let newNums = nums.filter(function(n) {
return n < 100
})
console.log(newNums);
</script>
let new2Nums = newNums.map(function(n) {
return n * 2
})
console.log(new2Nums);
//preValue:前面值得累加,有点像sum
//n:数组中的值,
let total = new2Nums.reduce(function(preValue, n) {
return preValue + n;
}, 0)
console.log(total);
const aaa = function(){
}
const obj = {
bbb:function(){
},
bbb(){
}
}
const ccc = (参数列表)=>{
}
<script text="javascript">
//参数问题:
//1.1放入两个参数
const sum = (num1,num2)=>{
return num1+num2
}
//1.2放入一个参数(一个参数的时候,参数括号可以省略)
const power =num=>{
return num * num
}
//2函数代码块有多行代码的时候
const sss = test=>{
//1.打印HelloWord
console.log(HelloWord)
//2.打印total
console.log(total)
}
//2.1函数代码块有一行代码块的时候 不用写return
const nul = (num1,num2)=>num1+num2
</script>
在非箭头函数下, this 指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链, getter & setter等都适用);构造函数下,this与被创建的新对象绑定;DOM事件,this指向触发事件的元素;内联事件分两种情况,bind绑定, call & apply 方法等, 容以下一步一步讨论。箭头函数也会穿插其中进行讨论。
在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;
console.log(this.document === document); // true
// 在浏览器中,全局对象为 window 对象:
console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37
普通函数内部的this分两种情况,严格模式和非严格模式。
非严格模式下,this 默认指向全局对象window
function f1(){
return this;
}
f1() === window; // true
而严格模式下, this为undefined
function f2(){
"use strict"; // 这里是严格模式
return this;
}
f2() === undefined; // true
对象内部方法的this指向调用这些方法的对象,
<script text="javascript">
//1
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); //37
var a = o.f;
console.log(a()): //undefined
var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37
//2
o.b = {
g: independent,
prop: 42
};
console.log(o.b.g()); // logs 42
</script>
箭头函数中的this引用的是最近作用域中的this
待总结… console.log(newNums);
##### 1.1.2map函数的使用:
- 让数组中的值都有一次变化的话用**map**(例如:数组中的每一个值都乘以2)
```vue
let new2Nums = newNums.map(function(n) {
return n * 2
})
console.log(new2Nums);
//preValue:前面值得累加,有点像sum
//n:数组中的值,
let total = new2Nums.reduce(function(preValue, n) {
return preValue + n;
}, 0)
console.log(total);
const aaa = function(){
}
const obj = {
bbb:function(){
},
bbb(){
}
}
const ccc = (参数列表)=>{
}
<script text="javascript">
//参数问题:
//1.1放入两个参数
const sum = (num1,num2)=>{
return num1+num2
}
//1.2放入一个参数(一个参数的时候,参数括号可以省略)
const power =num=>{
return num * num
}
//2函数代码块有多行代码的时候
const sss = test=>{
//1.打印HelloWord
console.log(HelloWord)
//2.打印total
console.log(total)
}
//2.1函数代码块有一行代码块的时候 不用写return
const nul = (num1,num2)=>num1+num2
</script>
在非箭头函数下, this 指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链, getter & setter等都适用);构造函数下,this与被创建的新对象绑定;DOM事件,this指向触发事件的元素;内联事件分两种情况,bind绑定, call & apply 方法等, 容以下一步一步讨论。箭头函数也会穿插其中进行讨论。
在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;
console.log(this.document === document); // true
// 在浏览器中,全局对象为 window 对象:
console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37
普通函数内部的this分两种情况,严格模式和非严格模式。
非严格模式下,this 默认指向全局对象window
function f1(){
return this;
}
f1() === window; // true
而严格模式下, this为undefined
function f2(){
"use strict"; // 这里是严格模式
return this;
}
f2() === undefined; // true
对象内部方法的this指向调用这些方法的对象,
<script text="javascript">
//1
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); //37
var a = o.f;
console.log(a()): //undefined
var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37
//2
o.b = {
g: independent,
prop: 42
};
console.log(o.b.g()); // logs 42
</script>
箭头函数中的this引用的是最近作用域中的this
待总结…
以上是脚本宝典为你收集整理的vue笔记详解全部内容,希望文章能够帮你解决vue笔记详解所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。