【2022.3】尚硅谷Vue.js从入门到精通基础笔记(理论+实操+知识点速查)
前言
爆肝15天,本文共4万5千字,包含Vue.js理论到实战。知识点全部都能使用ctrl+f速查,可作为知识点速查笔记使用。
本文完全基于 参考资料:尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通加工整理而成,包括其代码,案例,资源等。前置知识是学习尚硅谷的视频教程,本文配合其教程食用,效果更佳。
本文全套资料、案例、源代码、插件已上传至Gitee:https://gitee.com/da-ji/full_stack_developer,大家需要可自取
b站直接搜索 vue ,第一条结果即是:
本文引入的vue版本是(2.4.1):
<!-- 引入Vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.4.1/dist/vue.js"></script>
目录
- 前言
- 一、通用概念、前置知识
- 1.1 MVC 和 MVVM
- MVC 架构(偏后端,以JavaWeb举例)
- MVVM架构(偏前端,以Vue举例)
- 1.2 WebPack基本概念 和 Vue-CLI
- 1.3 【面试】虚拟DOM(vitural dom)
- 虚拟DOM 和 v-for 中的key
- 【面试总结】总结key和虚拟DOM(react也有这概念)
- 1.4 vue官方文档和API
- 1.5 双向绑定概念
- 1.6 常用工具和资源,网站等
- bootcdn.cn (收集无数三方库、工具类)
- Vs Code 插件:Live Server
- Vs Code 插件:Auto Close Tag
- Vs Code 插件:Auto Rename Tag
- 其它实用VS插件:
- Vue Devtools
- 二、Vue 基础笔记
- 1、安装(引入)Vue.js
- 2、创建Vue对象,和Vue插值语法{{ xxx }}
- 【补充】el与data的两种写法(Vue实例管理)
- **el的另外写法如下:**
- **data的另一种写法(函数式)如下:**
- 【补充】创建Vue对象时,其它可配置属性
- 【methods】可以传各式各样的函数
- methods 中的 event
- 【重要】methods 调用 data 配置属性
- computed 计算属性
- watch 监视属性
- filters 过滤器
- template HTML模板
- 3、Vue指令语法
- 【v-bind】: 绑定html的标签属性:
- 【v-model】 双向绑定:
- 指令语法和插值语法的区别:
- 4、Object.defineProperty方法
- 常用属性之get和set
- 5、数据代理(数据劫持)
- Vue如何应用数据代理呢?
- 6、事件处理
- 6.1【v-on】绑定单击事件(结合前面讲的methods一起学习)
- 6.2事件修饰符
- 【JS基础之event】
- event的常用姿势:
- *event.preventDefault()*
- 常用事件修饰符(共六种):
- 键盘事件
- 7、计算属性(computed)
- 计算属性要解决的问题
- 计算属性使用案例
- **计算属性总结:**
- 计算属性简写
- 8、监视属性(watch)
- 监视属性的其它写法:
- 监视属性简写
- 深度监视
- 总结watch和computed
- 9、v-bind 绑定class、style样式
- A、绑定class
- B、绑定style
- 10、条件渲染(v-if、v-else、v-show)
- A、v-show (控制是否显示)
- B、v-if
- C、v-else-if 、v-else
- D、总结
- 11、列表渲染相关
- 11.1 v-for
- 11.2 key(面试常问)
- 11.3 列表过滤(模糊搜索)
- watch的实现方案:
- **使用computed 实现上面的功能**
- 11.5 【重要!面试题】Vue检测数据改变的原理
- 引入:
- 原因分析:
- 解决方案1:
- 解决方案2 (使用数组变更方法):
- 使用Vue内置set方法添加data对象没有的属性
- 总结:Vue检测数据改变原理
- 12、Vue收集表单数据
- 单选框(特殊)绑定技巧
- 多选框(特殊)绑定技巧
- 下拉框绑定技巧
- v-model 特殊用法
- 总结
- 全部演示代码:
- 13、Vue过滤器(Linux的管道符 |)
- 过滤器传参
- 全局过滤器和局部过滤器
- 14、Vue常用其他内置指令(简单)
- v-text
- v-html (动态渲染HTML带来的问题)
- 【补充知识】cookie机制和xss攻击
- xss攻击:
- v-cloak (n.斗篷 vt.遮盖;掩盖)
- JS阻塞
- v-once(只动态渲染一次)
- v-pre
- 15、Vue自定义指令
- 函数式指定(完成需求1)
- debug之大写驼峰命名法:
- 对象式指定(完成需求2)
- 全局自定义指令和局部自定义指令
- 总结
- 16、【面试】vue生命周期函数(也称钩子)
- **引入:**
- mounted(挂载):
- 生命周期函数的this问题:
- 其它的生命周期函数
- 钩子间变量传递小技巧(局部变量变全局变量)
- 路由相关的钩子函数
- 总结
- 三、Vue 组件化开发
- 1、组件基础概念
- 2、非单文件组件(是前置知识)
- **使用```Vue.extend```创建组件**
- **创建组件三部曲:**
- **非单文件组件注意事项(debug):**
- 组件的简写(直接写配置对象即可)
- 组件的嵌套
- VueComponent构造函数
- 【极其重要、面试】Vue原型链,和内置关系
- Vue 和 vm的关系
- VueComponent 和 VueComponent实例对象的关系
- **有了上面的铺垫,Vue有一个重要的内置关系:**
- 3. 单文件组件(.vue)
- 语法概述
- 组件的管理者,入口组件
- 4、Vue-CLI (Command Line Interface)
- 安装CLI、使用CLI创建启动工程
- 分析脚手架目录结构
- 配置文件
- 其他目录
- 其它注意事项:
- 引入静态资源文件(如bootstrap.css的方法)
- 总结文件结构
- 关于vue脚手架配置文件修改
- 关闭vue语法检查/语法检测:
- 5、组件开发其它相关属性
- 5.1 render函数(意为渲染)
- 5.2 $refs属性
- 概述
- 【重要】ref绑定组件标签
- **总结:**
- 5.3 props配置项(重要,可用于父子组件间传输数据)
- 自定义组件传入属性:
- props的三种写法(从简单到复杂)
- 总结:
- 更多案例:父组件利用v-for配合props,动态建立多个子组件
- 【重要】儿子如何给父亲传数据呢
- 【重要】兄弟组件之间如何传输数据
- 5.4 mixin(混入)
- 局部引入混合
- 全局引入混合
- 5.5 插件(install)
- 插件应用场景(类似于java的导jar包)
- 总结
- 5.5 scoped CSS样式作用域
- 6、TODO List 案例 (原始版本)
- 7、浏览器本地存储(localStorage,sessionStorage)
- **纯JS实现浏览器本地存储功能:**
- localStorage
- sessionStorage
- **总结:**
- 8、组件自定义事件($emit)
- 绑定(好几种写法):
- 解绑(this.$off)
- native修饰符(绑定原生标签,非自定义标签)
- 总结
- 补充(开发者工具事件视图)
- 9、全局事件总线
- 概念
- 原理
- 如何注册事件总线
- 使用事件总线任意组件传输数据:
- 总结
- 10、消息订阅与发布
- 11、$nextTick
- 12、过渡和动画
- Animate.css
- 总结
- 四、Vue ajax
- 1、前置知识和准备
- 2、Vue中axios的基本使用
- 【补充知识】ajax跨域问题
- 使用vue-cli搭建代理服务器
- 方法一(简单)
- 方法二:
- 综合案例(模拟请求)
- 3、vue-resource
- 4、slot插槽
- 最简单的插槽
- 具名插槽
- 作用域插槽(``````)
- 总结
- 五、vuex
- 1、基本概念和应用场景
- 2、[面试】Vuex工作原理
- 3、搭建vuex环境
- 4、实操(计算程序)使用vuex
- 5、Vuex开发者工具使用
- 6、getters配置项
- 7、mapState、mapGetters、mapActions、mapMutations
- mapState、mapGetters
- mapMutations、mapActions
- 8、vuex模块化(namespace)、ajax请求服务器
- 9、总结模块化
- 六、vue-router (路由)
- 1、概念
- 2、安装\引入\基础使用
- 需求引入
- 2.1 router的入口JS和基础引入
- 2.2 router-link、router-view、active-class
- 2.3 目录结构,几个注意点
- 3、嵌套路由(children)
- 4、路由传参之query参数
- 5、路由传参之params参数
- 6、命名路由(name属性)
- 7、路由的props配置
- 8、编程式路由导航($router)
- 9、缓存路由组件(``````标签)
- 10、两个新的生命周期钩子(仅在路由有)
- 11、路由守卫
- 11.1 全局路由守卫
- 全局前置路由守卫:router.beforeEach()
- 全局后置路由守卫:router.afterEach()
- 11.2 独享路由守卫(beforeEnter)
- 11.3 组件内路由守卫
- 12、路由器的两种工作模式(history、hash)
- 前端项目上线流程
- 总结
- 七、Vue UI 组件库
- Vue适配组件库推荐
- 组件的全部引入和按需引入
- 八、展望 Vue 3.0
- **课件位置:**
- 后记
一、通用概念、前置知识
1.1 MVC 和 MVVM
大家一说起MVC 都知道,但是和MVVM一对比就搞混了。这里举两个例子搞清楚MVC和 MVVM:
MVC 架构(偏后端,以JavaWeb举例)
该架构就是传统JavaWeb项目开发的一般模式,比较简单。
下面两张图截取自:MVC架构和SSM框架的个人理解,详情可直接移步该博客
MVVM架构(偏前端,以Vue举例)
前置知识是你得懂双向绑定:本文下面有讲解双向绑定,先看双向绑定。
一图说清MVVM(图来源自尚硅谷课件,本人进行二次加工):
在代码中体现上图中的Data Bindings(通过VM,将M绑定到View):
在代码中体现上图中的DOM Listeners(通过VM,将V绑定到M):
执行效果:
同时做到了将M绑定到V,和V绑定到M,就是实现了双向绑定。
VM(就是ViewModel),其实就是Vue实例本身,它负责将View和Model绑定起来
这就是Vue的MVVM体现!要理解透彻,需要对ViewModel,双向绑定,Vue实例都有详细的理解。其它前端框架对MVVM有不同的解释,但是原理和思想上是一致的。
最后看维基百科对其的定义:
1.2 WebPack基本概念 和 Vue-CLI
不需要全部学会WebPack这门技术,只是对其有一个基本认知即可。
它依赖于Node,可以使用npm安装;
使用npm init 指令构建 package.json 文件;
webpack 能够编译打包 js 和 json 文件。
能将 es6 的模块化语法转换成浏览器能识别的语法。
生产环境能压缩HTML,CSS,JS代码。
可以打包各种各样的资源:样式资源、图片资源、HTML资源,提取压缩css,js语法检查/兼容性处理。
那Vue-CLI是什么呢?其实就是Vue官方给我们构建的适用于.vue的打包构建工具
1.3 【面试】虚拟DOM(vitural dom)
虚拟DOM是内存中的数据,然后将虚拟DOM变成真实DOM。
原生js(不使用虚拟DOM):
Vue使用虚拟DOM方式:
虚拟DOM的好处:如上图,假如用了虚拟dom的技术,会将虚拟DOM和真实DOM比较(就是上图的diff算法),发现001,002,003是重复的。于是就不会再次渲染001,002,003. 而是复用它们。
只有004的虚拟DOM是不重复的,需要重新渲染。这就提高了展示效率。
虚拟DOM 和 v-for 中的key
v-for 中的 key,下文有提到。
虚拟DOM有一个比较算法,基于什么比较呢?就是基于key
这里直接看对应关系:
在进行渲染时,会将内存中的老虚拟DOM和新虚拟DOM根据key做比较,一旦发现虚拟DOM之间有变化,那么只重新渲染变化部分,复用未变化部分。所以 key 这个属性很重要。
一旦你的结构中包含输入类DOM,会产生错误DOM更新,导致界面渲染有问题。
【面试总结】总结key和虚拟DOM(react也有这概念)
1.4 vue官方文档和API
https://cn.vuejs.org/
官方推荐的Vue组件包:
1.5 双向绑定概念
https://blog.csdn.net/weixin_44757863/article/details/109110132
1.6 常用工具和资源,网站等
bootcdn.cn (收集无数三方库、工具类)
Vs Code 插件:Live Server
该插件真乃神器。内置小型Tomcat,以你在VS中打开的文件夹作为根资源,运行于一个小型的服务器。
该服务器的默认端口号为:5050
如下两张图所示,你就是只写了个HTML,也会给你跑在localhost:5050这个服务器上:
Vs Code 插件:Auto Close Tag
Vs Code 插件:Auto Rename Tag
其它实用VS插件:
JS Quick Console是真神器,快速生成console.log() 它不香吗?
Vue Devtools
在使用 Vue 时,我们推荐在你的浏览器上安装 Vue Devtools。它允许你在一个更友好的界面中审查和调试 Vue 应用。
如何安装:
在我的Gitee上的代码,已经上传该插件:https://gitee.com/da-ji/full_stack_developer,大家需要可自取
固定该程序(谷歌浏览器):
二、Vue 基础笔记
1、安装(引入)Vue.js
官网链接:https://cn.vuejs.org/v2/guide/installation.html
引入Vue之后,Vue就作为一个运行在全局的构造函数。我们可以使用这种方式直接创建一个Vue实例(点击直接跳转到本文2、创建对象)
1.1 原生安装方式:在HTML中使用JS标签引入
可以使用绝对路径和相对路径的方式。如果是绝对路径,就是https://这种直接引入互联网,如果是…/static 这种方式,就可以引入自己下载好的vue.js文件。
举例:
Vue-Cli
2、创建Vue对象,和Vue插值语法{{ xxx }}
下图一图便知:
关于上图的补充细节:
- 1、一个vue实例,只能绑定一个对应实例。这是一对一关系。多了就解析不了。
- 2、{{}} 插值语法,可以写JS表达式。(这点和thymeleaf有点类似)看下图例子:
【补充】el与data的两种写法(Vue实例管理)
el的另外写法如下:
原理是因为调用了原型链上的 $mount
属性:
至于什么是原型链,下面会讲解。现在只需要记住可以使用这种方法来绑定容器即可。
data的另一种写法(函数式)如下:
组件式开发全部都是函数式。该函数必须返回一个对象。
注意,这个函数,只能写成普通函数。如果写成箭头函数,箭头函数的this是window,普通函数的this就是Vue实现对象:
ES语法小课堂:
普通函数的this指向是调用它的那个对象,而箭头函数没有this,如果强制它this,由于无人调用,最终指向的就是window。
ES规范中,如果想在对象中写函数,还可以这样简写(和上图完全就是一个东西,只不过简写了而已):
就如上图那个data()一样,今后我们可以看到由很多由Vue管理的函数(Vue对象会调用它)。凡是由Vue管理的函数,都不能写成箭头函数,给老老实实的写成普通函数!
【补充】创建Vue对象时,其它可配置属性
刚刚只介绍了el和data,这里陆续介绍其他的。
【methods】可以传各式各样的函数
但是这个函数仍然受到Vue管理,所以不能写成箭头函数,只能写成普通函数。
methods是个对象,里面可以传入各式各样的函数。
传入的函数要符合:JS对象的某个属性是函数的语法规则。可以自行搜索JS对象中,如何让其某属性变成一个函数
举例:
methods 中的 event
event在不使用Vue时,可以通过windows.event
调用
在Vue中,如果你不传任何参数,methods中的函数可以自动获取到event:
Vue中,如果你想传一个实参event对象(event为浏览器内置的全局对象),不能直接写event,而是应该写:$event
如果你想用event,有一个【实参】占位符 $event
,可以传入event给形参中:
【重要】methods 调用 data 配置属性
使用this即可。
红色箭头是使用this获取到data的值,但是高明的地方在于蓝色箭头,因为蓝色箭头使用v-model,对data的属性进行了双向绑定,那么input框一旦改变,那么就会引起data改变,data改变从而引起methods里的自定义函数的返回值改变!!
computed 计算属性
点击直接页内跳转到计算属性这一章:
watch 监视属性
点击直接页内跳转到监视属性这一章:
filters 过滤器
点击直接页内跳转到过滤器这一章:
template HTML模板
下图是最简单的用法
不过一般不这么用,更多用法详见Vue组件开发一章。
3、Vue指令语法
前面在2里面讲了Vue插值语法 {{}},这里讲指令语法。
这一块和thymeleaf更像了,直接在标签上绑定就行。
【v-bind】: 绑定html的标签属性:
v-bind可以直接简写为 : (一个冒号)
v-bind: 后面的双引号,和{{}}插值语法一样,可以写JS表达式。
和thymeleaf一样,v-bind: 可以绑定任何标签。
【v-model】 双向绑定:
https://blog.csdn.net/weixin_44757863/article/details/109110132
补充两个注意事项:
1、如下图
2、v-model:value
的简写就是 v-model
。原因很简单,因为v-model只能应用在表单类(输入类元素)上。
例:
指令语法和插值语法的区别:
插值语法用于标签体,例:
<p>Hello,{{name}}</p>
而指令语法则是直接绑在标签的自定义属性上,例:
<a v-bind:href="defineUrl" v-bind:xxxx="hello">超链接</a>
4、Object.defineProperty方法
更高级的给对象添加属性方式。比原来的person.age这种方法高级的多,可以配置很多详细信息。
用法如下图,更多详细的配置对象属性可以自行百度。
如果设置了不可以枚举【默认就是不可枚举!】,那么就不能用for-each循环遍历对象属性了。
常用属性之:enumerable,布尔类型,默认值是false。如果想让该字段可枚举,就要显式设置为true。
常用属性之:configurable,布尔类型,默认值是false。控制字段是否可以被删除
常用属性之:writable,布尔类型,默认值是false。控制字段是否可以被修改
常用属性之:value,就是赋值,赋字段一个值。
常用属性之get和set
get和set这两个属性特别重要,所以单独拿出一节来讲解。
来看下面一个场景:
let number = 18let person = {name: "大吉",sex: "男",age: number}console.log(person.age) //输出18number = 22 //将number这个变量修改为22console.log(person.age) //输出仍然是18,而不是22
如果我们想让第二个console.log输出的是22呢?应该怎么操作?
这里就引入了我们强大的get和set功能了!!
- 接上图例子,使用get将输出修改为22:
let number = 18let person = {name: "大吉",sex: "男",age: number}console.log(person.age) //输出18Object.defineProperty(person, "age", {get() {console.log('有人读取了age属性')return number; //return值很重要}})number = 22 //将number这个变量修改为22输出的是22。只要有人读取age属性,就会调用get方法,get方法return的值就是number这个变量console.log(person.age) //22
执行效果如图所示:
所以我们通过get,实现了只要有人读取age属性,就可以执行get这个方法,至于get这个方法你里面想塞什么都可以。反正只要有人读取age这个属性,就执行get。
- 下面再看set方法:
let number = 18let person = {name: "大吉",sex: "男",age: number}console.log("number的值是:" + number) //18Object.defineProperty(person, "age", {//只要有人修改age属性//就会调用set方法,且会收到修改age属性的具体值set(value) {console.log('有人修改了age属性,age:' + value)//神奇的操作来了,我们让number这个变量修改number = value; }})person.age = 22 //修改age属性,从而调用set方法//非常神奇,我们明明修改了age,却能对number做修改console.log("number的值是:" + number) //22
执行效果图:
总结:通过get和set,使得操作对象更加灵活了
为什么要学这个Object.defineProperty方法呢?是为了下一节数据代理做准备!
5、数据代理(数据劫持)
概念:数据代理就是通过一个对象对另一个对象中属性的操作(读/写)
直接看下图:
上图中如果有人动了obj2,相当于通过obj2动了obj。 这就是最简单的数据代理实例
Vue如何应用数据代理呢?
通过数据代理,我们本应该操作vm._data.属性
,现在我们直接操作vm.属性
即可。
6、事件处理
6.1【v-on】绑定单击事件(结合前面讲的methods一起学习)
其简写是 @ 符号
举例:(下面两种方式等价。)
<button v-on:click="func1">按钮</button>
<button @click="func1">按钮</button>
如果你想传参(当然你的func1的定义处也需要定义形参才可以):
<button v-on:click="func1(a,b,c,d)">按钮</button>
如何将func1和func2被Vue管理呢?移步前文中的methods,一查便知。
6.2事件修饰符
对事件进行操作,前置知识是你得知道JS中的event。
【JS基础之event】
https://blog.csdn.net/lhjuejiang/article/details/79455801
event是一个内置的全局对象,我们看看里面有什么:
<button onclick="func1(event)">按钮</button>function func1(event) {console.log("我是个函数")console.log(event.target)}
上面的代码调用了func1,并且传入了全局的event,下面来看event的属性:
event的常用姿势:
event.preventDefault()
它可以阻止默认事件的发生。比如<a>
标签,其默认事件是跳转。如果我们想阻止单击超链接的跳转,可以这么玩儿:
<a href="https://www.baidu.com" onclick="func0(event)">超链接</a>function func0(event) {event.preventDefault()
}
此时打开控制台:
event的 defaultPrevent属性默认为false的,现在是true了。现在单击超链接将不会跳转。
回到事件修饰符中来,如果我们想在Vue中实现上述操作,需要怎么做呢?事件修饰符马上登场:
<div id="root"><a href="https://www.baidu.com" @click.prevent="func00(event)">被Vue管理超链接</a>
</div>
<script>new Vue({el: '#root',data: {},methods: {func00(event) {console.log("vue阻止页面跳转")}}})
</script>
上面一坨代码,和event.preventDefault() 是一样的效果。
@click.prevent
就是一个事件修饰符。
常用事件修饰符(共六种):
prevent、stop、once、capture、self、passive
stop可以阻止事件冒泡到它的上层;
once:once如果作用于按钮或者超链接,那么超链接只有第一次点击的时候 会跳转,除此之外该超链接将不会跳转。
键盘事件
以 @keyup.xxx 当键盘弹起 事件 为例:
有keyup当然就有keydown,当键盘按下立刻触发某事件。
上面的@keyup.esc
就是当esc键弹起,就触发showInfo这个自定义函数(该函数必须受Vue管理,即放在methods中)
其它常用的按键别名:
上图的2 解释:假如你想绑定CapsLock,你应该这样写:@keyup.caps-lock="xxxFunction"
,即转为小写且短横线命名。
【DEBUG:】似乎这里的事件修饰符绑定的函数不可以写 xxxFunction() 后面的小括号。否则会报错。必须把小括号去掉才可以。
7、计算属性(computed)
计算属性要解决的问题
计算属性要解决的问题是:插值语法{{}} 中,越来越长的JS表达式,不利于阅读和组件化的问题。
来看案例:
计算属性使用案例
计算属性和data联动,同样可以用this。看下例:
上图input框框中的 firstName、lastName 和下图 data中的 firstName、lastName 是双向绑定关系。
input框变化,data也会变。如果此时有人调用 计算属性中的fullName,那么fullName自然会变化。
计算属性中get还有一个属性:只要get里面绑定的data有变化,也相当于调用了一次vm中的 get() ,所以只要data里面的firstName和lastName变了,那么fullName即被调用。
执行效果图:
顺便一提,计算属性的属性也有set,和Object.defineProperty的set用法原理一样,如下图所示
计算属性总结:
为什么叫计算属性?它是根据 data
中,已经有的属性计算得出来的复杂属性。
计算属性简写
当你的计算属性只有人读,没有人修改,(也就是只有get没有set),那么计算属性可以简写为:
上图等价于下面的代码(其实就是简写了get,computed是一个对象,对象的 fullName 字段是一个函数而已):
computed: {fullName: {get() {console.log('get被调用了')return this.firstName + '-' + this.lastName}}}
8、监视属性(watch)
概念作用:监视属性仍然是监视 data 的属性变化(也可以监视计算属性!)。
监视属性的传值是一个配置对象。
当data里面的某字段发生变化,就调用handler函数,handler函数里面有两个入参,分别是newValue、oldValue,顾名思义代表修改前和修改后。如下图所示:
如果被监视结构是多级的:
data:{numbers:{a:1,b:1}
}
那么应该这样配置:
watch: {'numbers.a': { //这样配置多级结构handler() {console.log("a被改变了")}}}
监视属性的其它写法:
调用vm的$watch方法:
这种写法可以简写。但是简写的前提是:watch的配置项只有handler一个参数!!!!,不能有什么deep啊,immediate之类的。
简写办法:
监视属性简写
简写的前提是:watch的配置项只有handler一个参数!!!!
immediate :true 初始化时让handler调用一下。
什么immediate 啊,deep啊,都不能写,才能用这个缩写。
深度监视
深度监视是默认关闭的。
场景如下:
如果被监视结构是多级的:
data:{numbers:{a:1,b:1}
}
如果你想监测 numbers.a 的变化,上文已经讲过如何监视了。这里不做讲解。但是如果a变化了,那么numbers应该是也变化的。但是Vue却不认为numbers变化了!此时你再监视numbers,假如numbers.a被修改,那么Vue不认为numbers被修改。
如下所示:
watch: {numbers: {handler() {//就算numbers.a变了,下一句也不会执行console.log("numbers被改变了")}}}
解决方案:打开深度监视:
watch: {numbers: {handler() {deep:true, //开启深度监视//numbers.a变了,下一句会执行console.log("numbers被改变了")}}}
深度监视总结;
总结watch和computed
如果是需要异步,请使用watch。因为computed依赖于get和返回值。
所有被Vue管理的函数,请写成普通函数。因为你需要让this的指向为vm
所有不被vue管理的函数,比如各种回调函数(定时器的回调函数,ajax的回调函数,promise的回调函数),最好写成箭头函数。这样this的指向才能指向它们本来应该指向的。如果你这里写成普通函数,就会造成调用失败,因为你的this指向了vm
因此,到底写普通函数还是写箭头函数,需要判断this指谁。如果需要this指向vm,必须写普通函数,否则(如果需要this指向其它调用者)请使用箭头函数。
9、v-bind 绑定class、style样式
A、绑定class
其实就是 v-bind 绑定一个class
可以如下图一样,写成数组,写成字段;也可以写成对象。
三种不同的写法:
先演示写成字段,和 写成数组:
最后演示写成对象(通过true和false决定对象内属性生效与否):
B、绑定style
- (常用)对象写法
如下图所示,对象写法里面的属性字段不能瞎写,需要下划线转驼峰的写法:
- 除了对象写法,还有数组写法(用的不多):
10、条件渲染(v-if、v-else、v-show)
A、v-show (控制是否显示)
v-show只能接收布尔类型(既可以直接写true,false;也可以写true和false类型的表达式):
<h1 v-show="1 === 3">大吉</h1>
这样写的话,h1这个标签就会隐藏,因为里面的值是false
也可以写data里面的类型为 true/false 的属性:
v-show隐藏掉的元素,只是样式隐藏不可见而已,但是元素还在(invisible = true)。但是下面的v-if却是直接干掉。
B、v-if
和v-show用法一致,填写一个布尔类型的表达式。
但是和show不同,元素被直接干掉了,而不是样式隐藏。
C、v-else-if 、v-else
一图便知:
如果在 条件判断之间,有元素将其打断:
那么后面就不生效了。
D、总结
11、列表渲染相关
11.1 v-for
最简单的实例:
形参还可以是两个参数:如下图所示;
第二个参数固定就是索引:
v-for还可以遍历对象(这里的第2个参数就不是索引了,两个参数分别是 value 和 key):
11.2 key(面试常问)
在使用for循环的时候,不管是vue还是react,都应该给每一个遍历生成的html元素取一个名字。这就是key
如果你不写key , 那么vue会自动将index作为key。但是非常建议你手动指定一个key。一般情况下不能不写key。index是什么?点我跳转
举例:
key还可以填入index:
如果你不写key,那么有可能会出现渲染错误的问题。为什么会出现这个问题呢?因为key和虚拟dom有关。
key的原理:和虚拟DOM相关,点我页内跳转:虚拟dom和key的对应关系。
最后看官方定义:
11.3 列表过滤(模糊搜索)
场景:
watch的实现方案:
下面代码难点如下:
- immediate :true 初始化时让handler调用一下。
- JS基础:Array filter使用
- JS基础:indexOf使用
上述代码大概原理就是:
- 1、使用v-model让输入框中元素绑定到data的 keyWord中
- 2、使用watch监控keyWord,一旦keyWord改变了,立刻执行过滤关键字
- 3、一旦keyWord改变了,过滤关键字之后会返回一个全新的数组,将该数组赋值给data的 filPerson中
- 4、filPerson负责被前端的v-for遍历,显示过滤后(模糊查询后)的结果
使用computed 实现上面的功能
上述代码大概原理就是:
1、使用v-model让输入框中元素绑定到data的 keyWord中
2、利用filter,输入框变化引起keyword变化引起persons变化
3、建立计算属性filPersons,当persons有变化,那么就重新计算一次filPersons。
4、filPerson负责被前端的v-for遍历,显示过滤后(模糊查询后)的结果
11.5 【重要!面试题】Vue检测数据改变的原理
本章Demo引入的vue版本是(2.4.1),如果版本太新会报错:
<!-- 引入Vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.4.1/dist/vue.js"></script>
引入:
需求:点击按钮,只修改马冬梅的信息:
代码编写:
在上图代码中:方式1生效,方式2不生效。这是为什么??Vue不承认方式2吗??
原因分析:
直接赋值的方式,不被vue认为是响应式的。
解决方案1:
不谋求修改数组单个元素,而是替换整个数组。类似这样:
this.persons = {{id:001, name:'马老师',age:50,sex:'男'}, //替换该项{id:002, name:'周冬雨',age:33,sex:'男'},
{id:003, name:'周杰伦',age:33,sex:'男'},
{id:004, name:'周冬雨',age:33,sex:'男'}
}
替换数组 这里可以用filter、concat、slice实现:
解决方案2 (使用数组变更方法):
this.persons.uns![在这里插入图片描述](https://img-blog.csdnimg.cn/196d56229b1e47fbb119c21c7ca6fa01.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQOWkp-WQiQ==,size_20,color_FFFFFF,t_70,g_se,x_16)
hift({ name: "jack", age: 70 })
对Array进行操作,而且想让Array仍旧是响应式,必须使用Vue给我们内置的七个方法:
原生JS这么多操作数组的方法,为什么只有这7个被Vue封装呢?因为这7个元素会改变原生数组。判断依据就是该方法会不会改变原生数组!
为什么上面的解决方案生效呢?因为Vue帮我们封装了数组的常用方法:
push、pop、shift、unshift、splice、sort、reverse
vm的push 和 Array的push方法不一样,vue帮我们做了两件事:
- 1、调用了原生数组的push
- 2、触发视图(viewmodel)的更新
使用这种方式增改Array元素,可以使用 = 等于号对其中的对象赋值,其赋值仍旧是响应式的! 不用非得使用vue内置set方法赋值!
使用Vue内置set方法添加data对象没有的属性
假如你的dom想添加一个vue的data没有的属性呢?注意是添加没有的,而不是修改现有的。
添加之前没有的,根据上面的Vue检测数据改变的原理, 我们必须使用内置的set方法才能添加一个响应式的data属性。
直接看案例:点击按钮,给vm添加data属性并展示:
使用Vue.set 可以实现。
绝对不能使用: this.student.sex = “男” 这种方式!!
判断是否真的是响应式,依据就是该属性有没有 getter 和 setter(下图就是响应式的):
总结:Vue检测数据改变原理
本章全部演示代码如下所示
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="root"><button @click="student.age++">年龄+1岁</button> <br /><button @click="addSex">添加性别属性</button> <br /><button @click="student.sex = '未知' ">修改性别属性</button> <br /><button @click="addFriend">在列表首位添加一个朋友</button> <br /><button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br /><button @click="addHobby">添加一个爱好</button> <br /><button @click="updFirstHobby">修改第一个爱好为:开车</button> <br /><h3>姓名:{{student.name}}</h3><h3>年龄:{{student.age}}</h3><!-- 只有vm._data有性别才会显示这个标签 --><h3 v-show="student.sex">性别:{{student.sex}}</h3><ul><li v-for="(h,index) in student.hobby" :key="index">{{h}}</li></ul><h3>朋友们</h3><ul><li v-for="(f,index) in student.friends" :key="index">{{f.name}}--{{f.age}}</li></ul></div></body><!-- 引入Vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.4.1/dist/vue.js"></script>
<script>//创建Vue实例const vm = new Vue({el: '#root',data: {student: {name: "大吉",age: 18,hobby: ["抽烟", "喝酒", "烫头"],friends: [{ name: "friends1", age: 35 },{ name: "friends2", age: 36 }]}},methods: {addSex() {debugger;//Vue.set(this.student, 'sex', '男') //方式1,必须这样做才能响应式this.$set(this.student, 'sex', '男') //方式2,必须这样做才能响应式},addFriend() {this.student.friends.unshift({ name: "jack", age: 70 }) //必须这样做才能响应式},updateFirstFriendName() {this.student.friends[0].name = "张三"},addHobby() {this.student.hobby.push("学习")},updFirstHobby() {this.student.hobby.splice(0, 1, "开车")}}});</script></html>
12、Vue收集表单数据
单选框(特殊)绑定技巧
如果input type 是一个radio(复选框),这里较为特殊:
<!-- v-model 只能收集value值 -->男<input type="radio" v-model="sex" value="male" name="sex">女<input type="radio" v-model="sex" value="male" name="sex"> <br /><br />
需要v-model绑定data属性的同时,指定value值(value可相等)
多选框(特殊)绑定技巧
如果input type 是一个checkbox(复选框),这里较为特殊:
必须保证绑定data数据是数组,同时必须指定不相同的value:
为啥是数组呢?因为这是多选框,要多选啊!肯定是数组!
效果如图(为什么必须用数组接收):
下拉框绑定技巧
如果input type 是一个select 和option (下拉框)
因为 option里面有value属性,所以只需要绑定select即可(option只需要写入value,该value会和vm互动):
<select v-model="city"><option>请选择校区</option><option value="beijing">北京</option><option value="shanghai">上海</option><option value="shenzhen">深圳</option><option value="wuhan">武汉</option></select>
v-model 特殊用法
去掉前后空格,只需要 v-model.trim
即可:
总结
全部演示代码:
效果:
代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<div id="root"><form>账号:<input type="text" v-model="name"> <br /><br />密码:<input type="text" v-model="password"> <br /><br />性别:<!-- v-model 只能收集value值 -->男<input type="radio" v-model="sex" value="male" name="sex">女<input type="radio" v-model="sex" value="female" name="sex"> <br /><br />爱好:学习<input type="checkbox" v-model="hobby" value="study">打游戏<input type="checkbox" v-model="hobby" value="game">吃饭<input type="checkbox" v-model="hobby" value="eat"><br /><br />校区:<select v-model="city"><option>请选择校区</option><option value="beijing">北京</option><option value="shanghai">上海</option><option value="shenzhen">深圳</option><option value="wuhan">武汉</option></select><br /><br />其他信息:<textarea></textarea> <br /><br /><input type="checkbox" v-model="agree">阅读并接受<a href="www.baidu.com">《用户协议》</a><button>提交</button></form>
</div><body></body><script src="https://cdn.jsdelivr.net/npm/vue@2.4.1/dist/vue.js"></script>
<script>const vm = new Vue({el: '#root',data: {name: "",password: "",sex: "male", //默认是男hobby: [],city: "beijing",other: "",agree: ""}});</script></html>
13、Vue过滤器(Linux的管道符 |)
这章能实现的功能,使用method,和computed完全能实现,只不过过滤器能够进一步的简化而已。
直接看例子:
过滤器传参
如果只传一个参数,那么默认肯定就是管道符前面的元素(很好理解,这和linux管道符是一样的)
但是过滤器也可以传入多个参数:
其中第一个参数,一定是管道符前面的元素,只有第二个参数才是自定义的参数:
全局过滤器和局部过滤器
之前写的是局部过滤器,只有一个vm能用。
下图展示了全局过滤器:
14、Vue常用其他内置指令(简单)
之前学过的指令:
v-text
v-html (动态渲染HTML带来的问题)
比起v-text更高级的地方:可以解析html标签:
效果如下:
但是这种方法是有风险的:
在网站上动态渲染HTML非常危险,容易导致XSS攻击!,比如窃取cookie!
【补充知识】cookie机制和xss攻击
cookie机制
跨浏览器读取Cookie是不生效的:
里面包含了我们的用户信息,权限校验等等各种信息
这也就解释了使用postman调用某些网站接口调用不通,必须得有cookie才能调用通过。
而cookie包含了一系列权限校验信息。
查看cookie 如下图所示:
也就是说:假如有人得知了我们的某网站的cookie全部信息,并且将这些cookie设置到该人的浏览器上,那么该人不用登录就可以登陆到你的账号上了!!
xss攻击:
XSS的攻击方式就是想办法“教唆”用户的浏览器去执行一些这个网页中原本不存在的前端代码。
比如使用 document.cookie
命令,窃取用户的cookie信息!
v-cloak (n.斗篷 vt.遮盖;掩盖)
JS阻塞
如下图所示,如果JS代码引入在body之外:
一旦链接阻塞,上图会让整个浏览器阻塞5秒,等JS全部加载出来,才能渲染界面!
但是如果JS像下图一样引入:
v-cloak作用是配合css使用。在JS阻塞(vue.js加载不出来)之前,v-cloak标签会被自动移除。也就是说,只要vue.js加载出来,那么v-cloak标签就不存在。
上图中,如果遇到JS阻塞,h2会被css控制而不显示。一旦vue.js被加载出来,v-clock将不存在。从而使CSS代码失效,h2会显示出来。
v-once(只动态渲染一次)
v-pre
vue不会解析带有v-pre的节点。这个节点不能乱用,只有优化性能时候用得到
15、Vue自定义指令
需求:
函数式指定(完成需求1)
debug之大写驼峰命名法:
所以在官方风格指南中,如果遇到长单词,别用驼峰了,用短横线。
对象式指定(完成需求2)
对象式指定比较高级,它能完成所有函数式指定的功能,并且还能自定义调用时机
对象式指定,必须写Vue给我们规定的函数名,否则不予解析。常用的函数名有三个:bind、inserted、update
上图的三个函数(bind、inserted、update),其形参都可以接收到【函数式指定】说的element和binding这两个形参。
bind、inserted、update 三种方法,就是vue解析的三种不同的时机。在vue解析的不同时刻,每一个时间点,vue会帮我们调用这三种不同的函数之一。
全局自定义指令和局部自定义指令
和前面的全局过滤器和局部过滤器规范完全一致:
函数式指定全局:
对象式指定全局:
区别就是第二个参数到底是传对象还是传函数而已。
总结
16、【面试】vue生命周期函数(也称钩子)
react也有类似的钩子概念,和vue的概念类似
引入:
需求:做一个这个效果:
方式一(不推荐):
下面这种方法依赖于形参vm。并没有集成在Vue初始化里面。
<body><div id="root"><h2 :style="styleObj">欢迎学习vue</h2></div>
</body><script src="https://cdn.jsdelivr.net/npm/vue@2.4.1/dist/vue.js"></script>
<script>const vm = new Vue({el: '#root',data: {styleObj: {//opacity 是style的样式,负责控制透明度opacity: 0.5,color: "orange"}},});//方式1:通过操作vm的样式(不推荐)setInterval(() => {vm.styleObj.opacity -= 0.01if (vm.styleObj.opacity <= 0) vm.styleObj.opacity = 1}, 16);
</script>
方式二:破坏了原来需求(需要点一下才能触发)
上面两种方法均无法完成需求,下面使用mounted将需求完成:
mounted(挂载):
概念:vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕),会调用mounted。mounted只会被调用一次。
使用mounted完成上述需求:
<body><div id="root"><h2 :style="styleObj">欢迎学习vue</h2></div>
</body><script src="https://cdn.jsdelivr.net/npm/vue@2.4.1/dist/vue.js"></script>
<script>const vm = new Vue({el: '#root',data: {styleObj: {//opacity 是style的样式,负责控制透明度opacity: 0.5,color: "orange"}},methods: {},mounted() {console.log("vue模板被解析完成,会调用我一次!")setInterval(() => {this.styleObj.opacity -= 0.01if (this.styleObj.opacity <= 0) this.styleObj.opacity = 1}, 16);},});</script>
完美实现!
通过观察上述mounted用法,可以知道,mounted其实就是一个普通的函数。这个函数的调用时机,其实就是DOM加载完毕后,且只会被调用一次。
mounted就是一个vue生命周期函数。
生命周期函数的this问题:
生命周期函数的this已经被维护好,就是指vm。所以里面如果需要用到的函数形参会传入箭头函数(比如上面的setInterval,第一个参数就是箭头函数),就应该写箭头函数!该箭头函数里面的this,就会找到vm本身!
其它的生命周期函数
来源于官网的生命周期图示:
尚硅谷更进一步的解释:
上图中红色框框的,都是生命周期函数(可以像mounted那样去调用)
vm.$destroy()
用于完全销毁一个vue实例。
钩子间变量传递小技巧(局部变量变全局变量)
利用钩子函数的this就是指vm本身的特性,可以将局部变量挂在vm上,这样钩子间局部变量就成了共享的全局变量了
例子:
解决方案:将id这个变量挂在vm上,它就成了全局的了:
路由相关的钩子函数
前置知识是路由,移步路由章节。
总结
其实能够得最多的两个钩子就是mounted和beforeDestroy两个
三、Vue 组件化开发
1、组件基础概念
传统方式开发的痛点和引入组件的好处:
vm对象和组件的关系:
首先,只有一个vm对象。剩下的都是组件,组件又称小vm,具有部分vm功能:
2、非单文件组件(是前置知识)
先学这个。
使用Vue.extend
创建组件
里面传入的配置对象,和new Vue的时候传入的配置项几乎一致,但是有下面几点需要注意:
- 一定不要写el配置项。因为组件的定义决定了,组件作为模块化开发的一块砖,哪里需要哪里搬。所以组件不需要对任何父组件负责,只对vm本身负责。
- data必需写成函数式,否则报错。原因和上面一样,组件如果被多次引用,写成函数可以保证局部的封装性。
- 使用template对html进行渲染, 注意template内的html只能有一个根元素。
- 组件分为局部组件和全局组件。 注册全局组件只需要
Vue.component('组件名',要注册的组件位置)
即可。通常这两个参数是一样的
创建组件三部曲:
代码如下:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="root"><!-- 第三步:在root中编写组件标签 --><xuexiao></xuexiao><xuesheng></xuesheng></div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.4.1/dist/vue.js"></script>
<script>//第一步:创建组件1const student = Vue.extend({//使用template对html抽出来(组件化)。注意template内的html只能有一个根元素。template: `<div><h2>姓名:{{name}}</h2><h2>年龄:{{age}}</h2></div>`,data() {return {name: "大吉",age: "18"}},})//第一步:创建组件2const school = Vue.extend({template: `<div><h2>地址:{{address}}</h2></div>`,data() {return {address: "北京"}},})const vm = new Vue({el: '#root',//第二步:vm注册组件(局部注册)components: {xuexiao: school,xuesheng: student}});</script></html>
效果图如下:
非单文件组件注意事项(debug):
- 组件名的大小写问题会报错。要注意。
- 组件名和HTML元素不能重名
- 可以使用name字段指定组件在开发者工具中的名字(仅能骗过开发者工具而已)
组件的简写(直接写配置对象即可)
下面两种写法等价!
组件的嵌套
如下图:组件间有嵌套关系。
任务目标:
在Vue开发者工具中,实现下图嵌套结构:
【注】:标准化开发中,我们会建立一个组件,该组件只负责管理组件,不负责渲染数据。也就是说这个组件承担管理者角色,只对vm(root)负责。在上图中,app组件就承担了上述角色。
代码实现:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div id="root"><!-- 什么都不用写! --></div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.4.1/dist/vue.js"></script>
<script>//student写在上面,school在下。防止school引用不到儿子const student = Vue.extend({template: `<div><h2>姓名:{{name}}</h2><h2>年龄:{{age}}</h2></div>`,data() {return {name: "大吉",age: "18"}},})//school和student是父子关系const school = Vue.extend({template: `<div><h2>地址:{{address}}</h2><student></student> </div>`,data() {return {address: "北京"}},components: { //套娃,将儿子student引入进来student}})//hello和school是平级关系const hello = Vue.extend({template: `<div><h2>{{hello}}</h2></div>`,data() {return {hello: "hello"}},})//组件的管理者app(只对vm负责的组件,一人之下万人之上)//该组件不负责任何渲染。const app = Vue.extend({/* 下面千万别忘了用div包裹school和hello,因为只能有一个root */template: `<div><school></school> <hello></hello> </div> `,components: {school,hello}})const vm = new Vue({el: '#root',template: `<app></app>`,//第二步:vm注册组件(局部注册)components: {app}});</script></html>
VueComponent构造函数
组件是什么?如果我们输出一个组件会怎样?
发现它其实是一个函数,准确的说他是一个构造函数。
- 特别注意:每次调用
Vue.extend
,返回的都是一个全新的ViewComponent! - ViewComponent实例对象,以后简称vc
- vc中的this,指向vc本身;vm中的this,指向vm本身;
【极其重要、面试】Vue原型链,和内置关系
Vue 和 vm的关系
Vue是一个函数,vm是其new出来的实例对象
因此:vm.__proto__ === Vue.prototype
VueComponent 和 VueComponent实例对象的关系
VueComponent 是一个函数,VueComponent实例对象是一个对象
当渲染VueComponent时,VueComponent实例对象就被自动new出来了
因此:VueComponent实例对象.___proto___=== VueComponent.prototype.__proto__
有了上面的铺垫,Vue有一个重要的内置关系:
VueComponent.prototype.__proto__ === Vue.prototype
- 所以:
VueComponent实例对象.__proto__ === VueComponent.prototype.__proto__ === vm.__proto__ === Vue.prototype
- 有这个内置关系的原因是: 让VueComponent实例对象可以访问到Vue原型的属性和方法。
【补充】:JS原型相关知识:
注意:显式原型属性只有函数有,对象没有!对象只有隐式原型属性!
所以,函数.prototype 是一个对象。它再往上追溯原型链,就只能找__proto___
了
因此VueComponent.prototype.__proto__ === Vue.prototype
,对象===对象,这个等式成立。
那么 Vue.prototype(也就是vm.__proto__
)身上有什么呢? 有生命周期函数(mount, watch 等等):
继续走 :
函数实例的原型属性(函数对象.__proto___
),永远指向自己缔造者(函数)的原型对象(函数.prototype
)
原型链的尽头是Object,Object实例的原型属性指向null。这就是原型链的尽头了
如下图的绿色箭头,则可反映上述原型链关系:
最后一张图:
Vue这样做的目的:让VueComponent可以访问到Vue原型的属性和方法。
3. 单文件组件(.vue)
前置知识是非单文件组件,必需学那一章。否则看不懂.
语法概述
使用默认暴露方式将组件暴露出去(ES6模块化知识):
- 默认暴露
上图代码可以直接简写成:
【注】:如上图所示,name字段必须和文件名一致。这是约定俗成的规矩.
组件的管理者,入口组件
还记得上文讲单文件组件时提到的app组件吗?
在Vue模块化开发中,的确有这么个组件:
app组件写法如下:
app组件已经一人之下万人之上了。所以这就引出了入口组件,也就是vm:
在vue模块化开发中,使用main.js作为入口组件,它负责引入App.vue(管理者组件):
在html页面中,只需要准备好一个id为root的div,然后引入main.js ,即可。
4、Vue-CLI (Command Line Interface)
vue脚手架是vue官方提供的标准化开发工具(开发平台)
其实就是一个官方版本的webpack!
官方文档:https://cli.vuejs.org/zh/
安装CLI、使用CLI创建启动工程
NODEJS:更换淘宝镜像源
npm config set registry https://registry.npm.taobao.org
执行命令安装CLI:
npm install -g @vue/cli
如何用该脚手架创建工程:
cd到你想创建的目录
执行命令:
vue create 工程名
手动选择创建Vue2还是Vue3版本(这里选择Vue2)
cd到创建好的工程中,执行命令:
npm rum serve
如上图所示,一个内置的Tomcat就起来了,直接访问localhost:8080即可get到你的Vue项目。
神奇的是:下面这串地址Network,如果你同事(处在一个局域网环境下)输入了,也可以get到你的Vue项目!
分析脚手架目录结构
配置文件
package.json
node的知识点,符合NPM配置规范的会有这个文件。
web-pack里面的短命令也在其中。
babel.config.js
babel的配置文件,涉及到ES6转换ES5
package-lock.json
包版本控制文件。包括用到的插件,资源文件等等。
作用是以最快速度安装到指定版本,版本锁定功能在这个文件中锁着。
其他目录
main.js
就是上文说的入口组件。当
npm run serve
被执行了,就会执行main.js
其它注意事项:
- index.html的路径问题
内置了BASE_url,实际上指的就是./public 目录
引入静态资源文件(如bootstrap.css的方法)
总结文件结构
关于vue脚手架配置文件修改
关闭vue语法检查/语法检测:
在vue.config.js中配置:
lintOnSave:false
5、组件开发其它相关属性
5.1 render函数(意为渲染)
render 提供,提交,渲染
render函数的原生写法
通过原生写法,我们可以发现,它其实就等同于之前学非单文件组件中的创建vm样例中的template和components的功能。
但是我们一般不这样写render,而是使用简略写法:
其实就是帮我们创建模板,加载组件。
为什么要用render?因为vue-cli默认加载的是运行版本的Vue,它不认识 template和components这两个标签,所以只能用render。
5.2 $refs属性
概述
在Vue中,如果你想拿Dom元素,用下图的方法就不优雅了:
Vue解决的办法也很简单:设置一个$refs属性,该属性绑定在VueComponent实例对象(vc)上:
如果绑定在原生HTML标签上,本质就是给其加了个id属性(下图等价于上图)
【重要】ref绑定组件标签
如果ref绑定了一个组件呢?那么拿到的就是该子组件的vc。
app的vc有个ref属性,ref属性,ref属性,ref属性上有一个该子组件的vc
总结:
5.3 props配置项(重要,可用于父子组件间传输数据)
如果不是父子组件,还可以用其它方式传输数据。
需求引入:
如下图所示,Student.vue是一个组件。
我们想在下图中创建两个Student,每个Student分别有不同的数据。比如第一个student数据就如上图,但是第二个student数据 的name不叫张三了,想改成李四。
其实这个需求就是复用Student.vue 这个组件。
解决方案如下图:
自定义组件传入属性:
props可用于组件间传输数据(父组件传数据到子组件的data上)
传入侧:传入的属性一般是父组件(App.vue),也就是下图。
接收侧:而写props接收参数的一般是子组件。其实接收完props,相当于在自己的data属性中绑定了props的一些属性。
在想要被复用组件中,data部分字段可以写成props。如下图所示,共有三种写法:
props的三种写法(从简单到复杂)
总结:
这个props属性,其实就是data里的属性。props可用于组件间传输数据(父组件传数据到子组件的data上)data在vc身上,可以直接用this.xxx获取,那么props里面的字段自然也可以。
但是props的字段优先级高于data的字段,也就是说假如data和props有同名字段,vue会帮我们优先渲染props的值。
props字段一旦确定,不能被篡改。如果你想篡改,请利用data篡改props。
【注意】:props是只读的。Vue会对props的修改提出警告。如果你真要修改,请利用data篡改props。用v-model双向绑定props是高危操作,因为会引起props的修改!
更多案例:父组件利用v-for配合props,动态建立多个子组件
父组件传入代码:
<ul><MyItem v-for="(todoObj,index) in todos" :key="todoObj.id" :todo="todoObj"></MyItem>
</ul>
todos就是一个数组,里面有一堆不同的对象。todoObj是数组的每个元素。
todo就是要传给子组件的自定义属性,每次传输单个todoObj给子组件。注意要用 v-bind (
#[2022.3]尚硅谷Vue.js从入门到精通基础笔记(理论+实操+知识点速查) 前言 本文完全基于 参考资料:加工整理而成,包括其代码,案例,资源等.前置知识是学习尚硅谷的视频教程,本文配合其教程 ... 尚硅谷Vue2.0+Vue3.0全套教程丨vue.js从入门到精通 1.Vue核心部分 1.1 Vue简介 1.1.1 Vue是什么? Vue是一套用于构建用户界面的渐进式JavaScript框架. ... [Vue.js简介] Vue.js是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vue采用自底向上增量开发的设计.Vue的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整 ... 目录 第1章:Vue核心 1-1.Vue简介 1-1-1.什么是Vue 1-1-2.Vue的特点 1-1-3.搭建Vue开发环境 1-1-4.创建Vue对象 1-2.模板语法 1-3.数据绑定 1-4 ... PAAS 平台即服务 用户下单,云厂商,派出运维 构建 自动化运维工具-自动环境创建 docker公司 自动构建运行环境 容器的集群化 资源管理器 分布式系统内核 Twitter 改用k8s 退出历史 ... 内容很饱满,过程可能会枯燥,愿你经过风雨,过后能成为不一样的烟火 尚硅谷Vue系列教程学习笔记(2) 参考课程:<尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通> 参考链接:https://www.bilibili.com/video/ ... 尚硅谷Vue技术全家桶 课程来源于b站尚硅谷教程:一套搞定Vue技术全家桶,轻松拿捏vue3.0(vue.js全网最新) 课程简介 在这个vue2到vue3的过渡时期,需要兼顾2.x和3版本.尚硅谷的 ... 尚硅谷VUE项目-前端项目问题总结07---产品详情页 1.静态组件(详情页还未注册为路由组件) 2.发请求 3.vuex-获取产品详情信息 3.1放大镜 3.2 属性值[排他操作] 3.3轮播图[j ... 文章目录 一.需求案例 二.案例实现 2.1. 原始js写法 2.2. 怎样使用vue.js ? 2.3. 使用vue.js 写法 三.案例vue简述? 四.案例趣味延伸 五.表达值作用及嘱咐语 一. ...【2022.3】尚硅谷Vue.js从入门到精通基础笔记(理论+实操+知识点速查)相关推荐
最新文章
热门文章