VUE

Vue CLI3--运行单个 *.vue 文件

    1. 安装全局扩展

    npm install -g @vue/cli-service-global

    2. 运行.vue文件

    vue serve 文件夹名

注意: 如果已经安装过可以直接运行 vue serve 文件夹  运行时, 会自动生成一个 node_modules 文件夹

 

Vue官方api

JSON.parse(JSON.stringify(row))

JSON.parse('要转换的数据')

JSON.stringify('要转化的数据')

俩个方法的用法差别:

①.JSON.stringify是从一个对象中解析出字符串

②.JSON.parse是从一个字符串中解析出json(键值对)

主要用来解决:

  俩个地方同时调用一个数据 (v-model) 产生的变化 (相当于深拷贝)

 

数据可视化 D3.js

 想要修改vue项目自动开启浏览器 在config下的 index.js里的 module.exprots里的 dev项 修改

复制代码

复制代码

 module.exports = {

      dev: {

        host: 'localhost', // 可以被process.env.HOST覆盖 

        port: 3000, // 配置端口号 默认8080 

        autoOpenBrowser: true, // 是否自动打开浏览器 

        errorOverlay: true,

        notifyOnErrors: true, poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 

     }

复制代码

复制代码

 

 通过 Vue cli2 初始化项目

通过 vue init webpack 文件名称  创建vue项目()

输入上面命令后,会询问几个选项,根据自己需要填写就可以了。

一、Project name :项目名称,如果不需要就直接回车。注:此处项目名不能使用大写。
二、Project description:项目描述,直接回车
三、Author :作者
四、vue build 构建方式(暂且这么解释)
  两个选择(上下箭头选择,回车即为选定)(是使用阉割版的vue还是使用完整版的vue 第一个是完整版的 第二个是阉割版的)
  1.Runtime + Compiler:recommended for most users
  (译:运行+编译:被推荐给大多数用户)
  2.Runtime-only:about 6KB lighter min+gzip,but templates (or any Vue-specific HTML) are ONLY 
  allowed in .vue files-render functions are required elsewhere
  (译:只运行大约6KB比较轻量的压缩文件,但只允许模板(或任何VUE特定HTML)。VUE文件需要在其他地方呈现函数。翻译不精准,意思大概是选择该构建方式对文件大小有要求)
  这里推荐使用1选项,适合大多数用户的
五、install vue-router?是否安装vue的路由插件,需要就选y,否则就n(以下均遵循此方法)
六、Use ESLint to lint your code?是否使用ESLint检测你的代码?
  (ESLint 是一个语法规则和代码风格的检查工具,可以用来保证写出语法正确、风格统一的代码。)
七、Pick an ESLint preset:选择分支风格
  选项有三个
  1.standard(https://github.com/feross/standard) js的标准风格
  2.Airbnb(https://github.com/airbnb/javascript) JavaScript最合理的方法,这个github地址说是JavaScript最合理的方法
  3.none (configure it yourself) 自己配置
八、Set up unit tests? 是否安装单元测试(暂不详细介绍)
Pick a test runner 选择一个单元测试运行器
选项有三个
1.Jest(Jest是由Facebook发布的开源的、基于Jasmine的JavaScript单元测试框架)
2.Karma and Mocha
3.none
九、Setup e2e tests with Nightwatch(Y/n)?是否安装E2E测试框架NightWatch(E2E,也就是End To End,就是所谓的“用户真实场景”。)
Should we run 'npm install' for you after the project has been created?(译:项目创建后是否要为你运行“npm install”?这里选择包管理工具)
  选项有三个
  yes,use npm(使用npm)
  yes,use yarn(使用yarn)
  no,I will handle that myself(自己配置安装包)
一路回车到此等待安装完毕,会提示接下来的命令行

npm run dev  或者 npm run serve 运行项目

 

所创建的vue框架的文件说明

 

 

 

 

 另一种方法 Vue cli3初始化项目

vue create 文件名称

https://cli.vuejs.org/guide/creating-a-project.html#vue-create

 

在控制台运行 vue create 项目名称

会出现如下选项

 

此处有两个选项

Please pick a preset: (Use arrow keys)  // 请选择预设:(使用箭头键) 

default(babel, eslint)   // 默认套餐

Manually select features  // 自己去选择需要的功能,提供更多的特性选择。比如如果想要支持 TypeScript ,就应该选择这一项

  如果选择第二个会出现如下选项

 

 

vue-cli 内置支持了8个功能特性,可以多选:使用方向键在特性选项之间切换,使用空格键选中当前特性,使用 a 键切换选择所有,使用 i 键翻转选项。

 

对于每一项的功能,此处做个简单描述:

babel  网络

TypeScript 支持使用 TypeScript 书写源码。

Progressive Web App (PWA) Support PWA 支持。

Router 支持 vue-router 。

Vuex 支持 vuex 。

CSS Pre-processors 支持 CSS 预处理器。

Linter / Formatter 支持代码风格检查和格式化。

Unit Testing 支持单元测试。

E2E Testing 支持 E2E 测试。

那么基于开发常见的项目,同时兼顾项目健壮性的原则,本次选择如下特性支持:

 

 ②

Use class-style component syntax?  //使用类样式组件语法?

  这里是让选择在开发 Vue 组件时,要不要使用 class 风格的写法。为了更方便地使用 TypeScript ,此处选择 Y

 Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?  // 在TypeScript旁边使用Babel(对于现代模式、自动检测的polyfill、transpiling JSX是必需的)?

这个选项的意思是要不要使用 babel 工具自动为转换后的 TypeScript 代码注入 polyfiills 。如果实在搞不清楚具体是什么意思,可以先不用管,直接选择 Y ,进入下一步

④第四个选项

Use history mode for router? (Requires proper server setup for index fallback in production) // 使用路由器的历史模式?(需要为生产中的索引回退设置正确的服务器)

⑤第五个选项

这里就是说我们在项目里面需要支持何种动态样式语言,此处提供了三个选项:(此处选择 less)

 sass/scss

less

stylus  

 

 Pick a unit testing solution:  // 选择单元测试解决方案: 

? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? // 希望在哪里放置Babel、PostCSS、ESLint等的配置。

  In dedicated config files // 专用配置文件中

  In package.json  // 在 package.json中

这一步就是要选择配置文件的位置了。对于 Babel 、 PostCSS 等,都可以有自己的配置文件: .babelrc 、 .postcssrc 等等,同时也可以把配置信息放在 package.json 里面。此处出于对编辑器( Visual Studio Code )的友好支持(编辑器一般默认会在项目根目录下寻找配置文件),选择把配置文件放在外面,选择 In dedicated config files

? Save this as a preset for future projects?    // 此保存为将来项目的预设?

这个就是问要不要把当前的这一系列选项配置保存起来,方便下一次创建项目时复用。对于 MAC ,保存的配置信息会放在 ~/.vuerc 里面。

 

 

 

 

 

 

 

 

 

 

 mixins 作用: 把外界导入过来的行为,混入到 组件中 mixins 是与data平级的 他是一个数组

mixins: [] // 导入过来的行为
import min from '行为组件'
export default {
mixins: [ min ]
}

 

el: 接收 id和类名 用的

methods:绑定事件用的(用于定义的函数,可以通过 return 来返回函数值。)

data: 要渲染的内容(用于定义属性,实例中有三个属性分别为:site、url、alexa)

exit 终止终端运行

cls 清空终端

 

Vue.js是一套构建用户界面的框架,只关注视图(页面)层的开发

MVC 主要是后端的分层开发思想;把 一个完整的后端项目,分成了三个部分:

Model:(数据层)主要负责 数据库的操作;

View:(视图层)所有前端页面,统称为 View 层

Controller:(业务逻辑层)主要处理对应的业务逻辑;(对于后台来说,这是开发的重点)

MVVM是前端页面的分层开发思想,主要关注于 视图层 分离,也就是说:MVVM把前端的视图层,分为了 三部分 Model, View, ViewModel

Model 是 页面中,需要用到的数据

View 是页面中的HTML结构;

ViewModel 是 一个 中间的调度者,提供了双向数据绑定的概念;

为什么有了MVC还要有MVVM

因为 MVC是后端的开发思想,并没有明确定义前端的页面该如何开发;

MVVM 是前端的页面的开发思想,把每个页面,分成了三个部分,同时 VM 作为 MVVM 的核心,提供了双向数据绑定的概念,前端程序员,不需要手动渲染页面了,而且,页面数据发送变化,也不需要程序员手动把 数据的变化同步到Model中;这所有的操作,都是 VM 自动完成的!

有了 MVVM 的思想以后,前端只关心 页面交互逻辑,不关心页面如何渲染;

 

 

Vue.js基本代码和MVVM之间的对应关系

  1. 注意:Vue不推荐程序员手动操作DOM元素,所以,在Vue项目中,没有及其变态的需求,一般不要引入jQuery
  2. Vue代码解析执行的步骤:

(1) 当VM 实例对象,被创建完成之后,会立即解析el指定区域中的所有代码

(2) 当VM在解析el区域中所有代码的时候,会把data中的数据 按需添加到页面指定的区域

  1. 注意:每当vm实例对象 监听到data中的数据发生了变化,就会立即 重新解析执行el区域内所有的代码

 

Vue中的命令是:

定义: vue中通过一些特殊的语法,扩展HTML的功能

将来创建Vue实例的时候,Vue会把这些指令都进行解析,从而 根据不同的指令 执行不同的操作、渲染不同的结果

 

Vue指令:

插值表达式:插值表达式 {{}}   在指定的位置动态插入内容

1

2

<strong><div id="app">{{msg}}</div>

</strong>

 

v-cloak 解决插值表达式闪烁问题

当网络比较卡的时候,我们可以为最外层的div元素 添加 v-cloak 防止用户看到插值表达式

注意: 必须写一个css样式 [v-cloak]{ display:none} 不然没有效果

 

v-text 在元素的属性节点上 添加v-text 如:<p v-text="msg"></p> // 覆盖原有内容

不会解析标签

v-text 与 {{}}区别

是否覆盖内容

指令闪烁问题

 v-once 只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

 

 

 

 

 

v-html在元素的属性节点上 添加v-htmll如:<p v-html="msg"></p> // 覆盖原有内容

会解析标签

v-html 与 {{}}区别

是否覆盖内容

指令闪烁问题

 

v-bind: : 属性绑定

如:<button v-bind:title="titleStr">按钮</button>

应用场景:如果元素的属性值,需要动态地进行绑定,则需要使用v-bind: 指令

v-bind: 可以简写为 :

 

v-model实现双向数据绑定(v-model 指令用来在 input、select、text、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。)

可以把页面上数据的变化,自动同步更新到VM实例的data中

<input v-model="msg" /> // 等同于 <input :value="msg" @input="msg = $event.target.value" />

解释:

       $event 指代当前触发的事件对象。

       $event.target 指代当前触发的事件对象的dom

  $event.target.value 就是当前dom的value值

      在@input方法中,

        value => msg

        在: value中:

        msg => value

        如此,形成了一个闭环,也就是所说的数据的双向绑定。

 

v-model的修饰符

 v-model.lazy 只有在input输入框按回车键的时候和input失去焦点的时候才触发v-model

    v-model.trim 将用户输入的前后的空格去掉

    v-model.number 将用户输入的字符串转换成number

 

 

和 v-bind:的区别:

v-bind: 只能实现单向的数据同步 data ---> 页面;

v-model 可以实现双向的数据同步 data <--> 页面;

 

注意:

v-model 只能 和 表单元素 配合使用,例如 input、select、textarea 等;

v-model 是 Vue 中 唯一支持 双向数据绑定的指令;

 

在vue中使用 class样式

类名数组中使用三元表达式,按需为元素添加某些类名

不要让vue的实例对象 的el指向html和boty标签

<p :class=”[flag?’light’:’dark’]”></p> // 如果flag为真类名为light 为假类名为dark

 

 

Vue指令值v-for和:key 属性

语法:

1

2

<strong><li v-for=”循环的item项,索引 in 数组名”:key=””></li>

</strong>

只要用到了 v-for指令,那么必须带上 :key属性(只要有状态的情况下 必须带上 :key)

推荐,直接把item.id 当作key的值

在真是的项目中,调用API接口拿到的数据 都会包含ID 的

如:<li v-for="(item, key, index) in arr" :key="item.id">

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。

 key的作用是为了高效的更新虚拟DOM

 

Vue 指令 v-if和v-show

v-if 是动态的移除或者显示 判断的值如果是true 的话 显示  false 移除

v-show 是控制 display属性

v-if和v-show的作用,都是切换界面上元素的显示或隐藏的

一般来说,v-if有更高的切换消耗 二 v-show有更高的初始化渲染消耗

因此,如果需要频繁切换 v-show比较好 如果在运行时条件不太可能改变 v-if比较好

 

 

v-on: 事件绑定

v-on的作用,是为HTML元素绑定事件的处理函数 如:

<input type="button" value="按钮" v-on:click="事件处理函数名" />

v-on:click 可以简写为 @click

在事件定义时, 写方法时省略了小括号,但是方法本身是需要一个参数的,这个时候, vue会默认将浏览器产生的event事件对象作为参数传入到方法

方法定义时我们需要event对象同时用需要其他参数

在调用方法是,手动获取到浏览器参数的event对象 $event 

所有的事件在省略小括号的情况下, 系统会把event默认传递过去

 

 当methods中定义方法,以供@click调用时,需要主要参数问题:

①如果不需要额外的参数,那么方法后面的 () 可以省略

②如果方法本身有一个参数,那么会默认将原生事件 event参数传递过来去

③如果需要传入某个参数, 同时需要 event 时, 可以通过 $event传入事件

  

在所有的绑定事件中 事件处理函数都有一个默认的 event 参数

event.target始终指向事件发生时的元素,而event.currentTarget指向事件所绑定的元素。

 

 

事件修饰符

.prevent 阻止 submit提交、A标签默认行为跳转行为 (@click.prevent = "事件") 常用  对应event.preventDafault 阻止默认事件

.once 只触发一次

.stop 阻止冒泡 对应event.stopPropagation 阻止事件冒泡

.self 只有在当前元素上触发事件的时候,才会调用处理函数(不会阻止冒泡) 只有event.target 为自身才触发事件

.passive   滚动事件的默认行为(即滚动行为) 将会立即触发 而不会等待`onScroll` 完成 这其中包含`event.preventDefault()` 的情况

 .native  就是在父组件中给子组件绑定一个原生的事件,就将子组件变成了普通的HTML标签,不加'. native'事件是无法触  发的。

.self的理解

  我们知道在一般情况下,e.target总是指向最内层的元素 所以如果父元素设置了.self 修饰符 那么他在点击子元素时,并不会触发被修饰的事件;只有点击没有子元素的空白区域时,才会触发被修饰的事件

  官方文档的一个提示

  使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v - on: click.prevent.self 会阻止所有的点击,而 v - on: click.self.prevent 只会阻止对元素自身的点击。

事件修饰符可以连续多次调用

阻止跳转默认行为

只会阻止一次

 

按键修饰符(键盘按键) 按键修饰最好配合 input 输入框使用

按键修饰符都是配合文本输入框使用

.eneter  按回车键 才会触发

.tab 按tab键 才会触发

.esc  只有按ESC键的时候才会触发

.space 空格键

......... 所有键盘按钮都可以

@keyup.enter 按键盘回车才会触发

@keyup.键盘按键

 

通过全局 config.keyGodes 对象自定义按键修饰符别名

Vue.config.keyGodes.按键名 = 自定义按键

例: Vue.config.keyGodes.f2 = 112 

  

 

 

过滤器

概念:过滤器本质上就是一个函数,可以被用作一些常见的文本格式化

过滤器只可以用在俩个地方: mustache(插值表达式) 和 v-bind:( 属性绑定)中

过滤器应该被添加在JavaScript表达式的尾部,有 管道符( | ) 指示

 

任何vue实例都可以调用全局过滤器

全局过滤器需要Vue.filter()来定义

私有过滤器需要定义到每个实例的 filters 属性中

私有过滤器只能被当前所属实例调用

全局过滤器

使用全局过滤器的语法: {{ msg |过滤器名称}}

定义全局过滤器的语法

Vue.filter(‘过滤器的名称’,function(originVal,pattern){
  /* originVal 管道符前面传递过来的值 */
  /* 传递的参数 */
  /* 对数据进行处理的过程 在这个function中,最后必须return一个处理的结果,否则就是一个非法的过滤器 */
})

 

注意:过滤器的处理函数,

形参列表中的第一个参数,永远都是 管道符 前面传递过来的值

   第二个参数是传的参数

过滤器不会修改原来的值

 // originVal 插值表达式  pattern 传入的参数

 

使用过滤器的注意事项:

1.如果想拿管道符前面的值,通过function的第一个形参来拿

2.过滤器中,一定要返回一个处理的结果,否则就是一个无效的过滤器

3.在调用过滤器的时候,直接通过( ) 调用就能传参,从过滤器处理函数的第二个参数开始接收传递过来的参数

4.可以多次使用 管道符(|) 一次调用多个过滤器 执行顺序是 从左往右执行

 

扩展

// 字符串新方法 string.prototype.padStart(填充完毕之后的总长度,以什么字符串进行填充) // 从前面添加

// 字符串新方法 string.prototype.padEnd(填充完毕之后的总长度,以什么字符串进行填充) // 从后面添加

可以给一位数时间自动补齐 0

使用Vue.filter创建的是全局过来器

私有过滤器 与el data 平级 创建一个 filters

私有过滤器

复制代码

复制代码

语法:
var vm = new Vue({
  el: '#app',
  data: {},
  filters: {
  // 这是 古老的 ES3写法
  过滤器的名称: function(originVal){},
  // 这是最新的ES6写法【推荐】
  // '过滤器名称':'过滤器处理函数'
  过滤器的名称(originVal){ return 处理的结果 } } })


filters('my-filter', function (value) { // 返回处理后的值 })

复制代码

复制代码

 

 

 

 注意:过滤器查找顺序问题,就近原则

Vue.$mount( ) 与el用法相同 在没有el的时候 用Vue.$mount() 动态挂载实例对象

语法: Vue.$mount(“选择器- 指定要控制的区域”)

Vue.$mount( )  手动控制要指定的区域

 

template 属性指定模板

template和data平级 ,会替换到el所指定的区域

如果在new Vue实例的时候,既指定了el 又指定了template,则会把template指定的模板结构,替换掉el的模板结构 

 

什么是生命周期

生命周期:实例的生命周期,就是一个阶段,从创建到运行再到销毁的阶段

生命周期函数:在实例的生命周期中,在特地阶段执行的一些特定事件,这些事件叫做生命周期函数

  生命周期函数又叫 --生命周期钩子--生命周期事件

 

 

生命周期函数分类

Vue的三个阶段(创建阶段->运行阶段->销毁阶段)

生命周期:每个Vue实例,从创建到运行 再到销毁的整个阶段,就是完整的生命周期

生命周期函数: 在每个实例的生命周期中,都会依次按顺序调用固定个数的函数,这些函数,叫做生命周期函数

生命周期函数是由框架开发人员预先定义好的,每个实例在创建,运行,销毁的过程中,都后悔依次顺序 自动调用这些函数

程序员要做的事情就是在这些固定的函数中,左自己指定的业务处理就行

创建期间的生命周期函数:(特点:每个实例一辈子只执行一次)

  1、beforeCreate:创建之前,此时 data 和 methods 尚未初始化 (当执行到 beforeCreate生命周期函数时,当前Vue实例的data和methods方法,都还没有初始化完成,因此,这个函数对于我们没有太大的意义)

  2、created 第一个重要的函数,此时,data 和 methods 已经创建好了,可以被访问了 (当执行到created生命周期函数的时候,实例的data数据和methods方法,都已经被初始化完毕,可以被正常访问 [一般首屏数据的Ajax请求,都要在created中发起ajax])

  3、beforeMount:挂载模板结构之前,此时,页面还没有被渲染到浏览器中;(此时,浏览器中的页面还是假页面,并不是真正带有数据的页面,在这个函数里插值表达式还没有解析好)

  4、mounted 第二个重要的函数,此时,页面刚被渲染出来;如果要操作DOM元素,最好在这个阶段 (第三方UI插件如果需要初始化 一定要写在mounted中) 

        创建页面结束

运行期间的生命周期函数:(特点:按需被调用 至少0次,最多N次)

  5、beforeUpdate:将要根据最新的data数据,从新解析所有指令,从而重新渲染浏览器页面,此时 数据是最新的,而页面是旧的

    (中间会重新根据最新的data数据,解析所有指令,从而渲染并得到最新的页面,然后把渲染出来的新页面 替换到 浏览器中)

  6、updated:只要触发了updated,就说明,页面和数据都是最新的

销毁期间的生命周期函数:(特点:每个实例一辈子只执行一次)

  7、beforeDestroy:销毁之前,实例还正常可用

  8、destroyed:销毁之后,实例已经不工作了

 

      beforeCreate(创建前),
      created(创建后),[主要发起Ajax 获取页面的首屏数据]
      beforeMount(载入前),
      mounted(载入后),[主要用来初始化第三方UI插件]
      beforeUpdate(更新前),
      updated(更新后),
      beforeDestroy(销毁前),
      destroyed(销毁后)

vue的生命周期(开始创建、初始化数据、编译模板、挂载Dom、渲染、更新、渲染、卸载)主要分为八个阶段:

beforeCreate data 和 $el 都没有初始化 全部为 undefined

created data 初始化完成,但 $el 没有初始化

beforeMount data 和 $el 均已存在,但 DOM 为虚拟DOM 仍未完全加载 eg: <div>{{message}}</div>

mounted data 和 $el 均已存在,并且 DOM 加载完成 ,完成挂载

当data中数据发生改变时触发update相关函数

beforeUpdate 渲染完成,并监测到data发生变化,在变化的数据重新渲染视图之前会触发,这也是重新渲染之前最后修改数据的机会

updated 监测到data发生变化,并完成渲染更新视图之后触发

beforeDestory 实例销毁之前调用 , 实例仍然完全可用。

destroyed 实例销毁后调用。调用后,实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

另外还有 keep-alive 独有的生命周期,分别为 activated 和 deactivated 。用 keep-alive 包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行 deactivated 钩子函数,命中缓存渲染后会执行 activated钩子函数。

vue生命周期的应用场景:

beforeCreate 可以在此时加一些loading效果,在created时进行移除

created 需要异步请求数据的方法可以在此时执行,完成数据的初始化

mounted 当需要操作dom的时候执行,可以配合$.nextTick 使用进行单一事件对数据的更新后更新dom

updated 当数据更新需要做统一业务处理的时候使用

 

下面是图解 ↓

 

Promise 的含义

Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise

所谓Promise ,简单说就是一个容器,里面保存着某个未来才回结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。 

Promise 对象的状态不受外界影响

 

Promise 概念:Promise 是ES6中的新语法,Promise是一个构造函数,每一个new出来的Promise实例对象,都代表一个异步操作

作用: 解决了回调地狱的问题

回调地狱,值得是回调函数中,嵌套回调函数的代码形式;如果嵌套的层级很深,就是回调地狱

回调地狱,不利于代码的阅读、维护和后期的扩展

 

创建形式上的异步操作

const p = new Promise()

 

创建具体的异步操作

const p =new Promise(function(success,error){// 在这和function中定义具体的异步操作})

success:是成功的回调  .then()的第一个function

error:是失败的回调   .then()的第二个function

 

// 1. Promise 是构造函数,可以被new;

// 2. new 出来的 Promise 实例对象,就表示 一个异步操作;

// 3. Promise.prototype 上,包含了 .then() 和 .catch() 两个方法;

  Promise.prototype.then()方法的作用,是为这个异步操作,预先指定 成功和失败的回调函数

  p.then(function(success){/* 成功的回调函数 */}, function(error){/* 失败的回调函数 */})

在使用Promise的时候,如果要捕获错误异常,推荐使用 .catch()

// 4. const p = new Promise() 这行代码,表示创建了一个【形式上的异步操作】;

// 5. const p = new Promise(function(){ /* 具体的异步操作 */ }) 在 new Promise() 的时候,传递的 function 函数,就表示一个具体的异步操作;你可以在 function 中,读文件、也可以 发Ajax;

// 总结:只要 new 了一个具体的异步操作,这个异步操作被创建的一瞬间,就会立即执行;

// 注意:在使用 .then() 方法的时候,失败的回调函数可以被省略;但是成功的回调必须要传递;

// 推荐:在使用 promise 的使用,如果要捕获错误异常了,直接使用 .catch() 就行

 

async 和await的作用

在使用 Promise 的时候最好使用async 

ES7中的async和await可以简化Promise调用,提高Promise代码的阅读性和理解性

async 是一个修饰符, 只能用来修饰方法;被async 修饰的方法,就是一个异步方法

await 只能用在被 async修饰的方法中 同时,await是用来修饰Promise实例对象的 要加在 Promise 之前

注意:async修饰的方法中,在遇到 第一个await之前,所有的代码都是同步执行的, 直到 遇到第一个await开始,其他的所有代码,都是以异步形式来执行的

 

  

axios 的使用 https://www.npmjs.com/package/axios

安装: npm i axios

// 为 axios 挂载 全局的请求根路径

axios.defaults.baseURL = '挂载的地址'

// 把axios 挂载到 vue上  调用名是$http

Vue.prototype.$http = axios

axios只支持get和post请求,无法发起JSONP请求

如果涉及到JSONP请求,可以让后端启用cors跨域资源共享即可

 

在Vue中,还可以使用 vue-resource发起数据请求

vue-resource支持 get、post、jsonp请求【但是,Vue官方不推荐使用这个包了】

 

只要导入了axios包,在window全局 就多了一个 axios成员

使用axios.get() 和 axios.post() 发送请求

axios.get(‘请求的地址’,{params{/* get 类型的参数 */}}) 

params是添加到url的请求字符串中的,用于get请求

axios.post(‘请求的地址’,{参数:  })

用这个插件发送请求

最好是先把 axios挂载到 Vue上

this.$http.get(‘请求地址’)

this.$http.post(‘请求地址’,{要提交的数据})

 

拦截器

 

问题

解决方法

  // 全局配置 axios 的 request 拦截器 
axios.interceptors.request.use(config => { 
    // 通过拦截request请求,主动为 请求头,追加新属性 Authorization,等于 token 值 
  config.headers.Authorization = window.sessionStorage.getItem('token') return config 
})

 

 

  

Vue动画

动画能够增加页面趣味性,目的是为了让永辉更好的理解页面的功能

注意: Vue中的动画,都是简单的过渡动画,并不会有CSS那么炫酷

  table 不知道过渡效果

 

Vue中的动画的基本介绍

每个动画分为两个部分 : 入场动画 和出场动画

入场动画分为两个时间点和一个时间段

v-enter入场前的样式

v-enter-to入场完成以后的样式

v-enter-active入场的时间段

离场时候Vue也把动画分为两个时间点和一个时间段

v-leave离场之间的样式

v-leave-to离场完成以后的样式

v-leace-active离场的时间段

 

元素在标准流中的样式,就是入场动画的终点状态,同时也是离场动画的起始状态

使用过渡类名

把需要添加动画的元素,使用v-if或者v-show进行控制

把需要添加动画的元素,使用Vue提供的元素 <transition></transition>包裹起来

(1) 如果transition没有显示定义的name属性,那么 它默认的name值为 v

(2) 可以自己定义name 值  定义好后只要把 入场和离场的 v 该成 自己定义的就可以了

(3) 为transition 添加两个属性: enter-active-class  和  leave-active-class  为需要过渡的元素 ,添加class=”animated” 类名 会有不同要是的动画效果 如: 抖动 跳动 ......等等样式 这个需要自己查询官方文档

 

添加两组类

.v-enter,

.v-leave-to{

    opacity: 0;

    transform: translateX(100px);

}

 

.v-enter-active,

.v-leave-active{

   transition: all 0.5s ease;

}

 

在用v-for 循环渲染的元素,添加 :key属性

在v-for循环渲染的元素外层,包裹 <transition-group></transition-group>标签

 

列表的排序过渡

<transition-group> 组件还有一个特殊之处。步进可以进入和离开动画,还可以改变定位。要使用这个新功能只需要理解新增 v-move特性,它会在元素的改变定位的过程中应用

v-move和v-leave-active 结合使用,能够让列表的过渡更加平缓柔和

/*控制要被删除的元素,脱离标准流*/

.v-leave-active{

  position: absolute;

}

 

/*控制后续的元素,通过过渡位移到目标位置*/

.v-move{

  transition: all 0.8s ease;

}

 

在网页中常引用的静态资源有:

 

样式表

.css  .less   .scss

 

JS文件

.js  .ts

 

图片

.jpg/.jpeg .png .gif .bmp .webp【webp的图片,在苹果手机的浏览器中显示不出来】

 

字体文件

.ttf .eot .woff .woff2 .svg

 

模板文件

.vue .jsx

 

网页中引入的静态资源多了以后的问题:

对网页性能不友好: 要发起很多的静态资源的请求,降低页面的加载效率 ,用户体验差

对程序开发不友好: 前端程序员要处理复杂的文件之间的依赖关系

 

对于JS文件或者CSS文件,可以合并和压缩; 小图片适合转 base64格式的编码

通过一些工具,让工具自动维护文件之间的一览关系

 

webpack

webpack 是前端项目的构建工具;前端的项目 都是基于 webpack进行 构建和运行的

如果项目中使用webpack进行构建,我们可以书写高级的ES代码;且不用考虑兼容问题

webpack能够优化项目的性能, 比如合并。压缩文件等

基于webpack 程序员可以把 自己的开发重心放到功能上

 

webpack非常适合于单页面应用程序结合使用

不太适合与多页面的普通网站结合使用

 

在项目中安装和配置webpack

webpack是前端的一个工具,这个工具 可以从NPM官网上下载到本地上使用

 

新建一个项目的空白目录,并在终端中 cd 到目录的根目录 执行 npm init -y 初始化项目

装包 运行 npm i webpack webpack-cli -D 安装项目构建所需的 webpack

在打开package.json文件, 在scripts节点中 新增一个 dev 的节点;(不一定是dev 名字可以根据需要填写) dev  是 development的简写 开发的意思

1

2

3

4

5

<strong>"scripts": {

    "test": "echo \"Error: no test specified\" && exit 1",

    "dev": "webpack"

  },

</strong>

4.在项目根目录中 新建一个 webpack.config.js 配置文件

// 这是 使用 Node 语法, 向外导出一个 配置对象

注意webpack.config.js 是webpack 的配置文件 webpack在运行和打包的时候,会优先读取这个配置文件中 导出的配置对象,根据用户指定的配置对象,来进行项目的编译

默认在webpack 4.x的版本中, 要打包的文件路径是scr下的index.js ,文件的输出路径是dist下的main.js

Webpack的配置文件中,支持使用module.exports 语法,因为webpack这个工具 就是基于node创建的

1

2

3

4

5

6

7

<strong>注意: webpack.config.js 是webpack的配置文件</strong><br><strong>webpack 在运行和打包的时候,会优先读取这个配置文件中导出的配置对象</strong><br><strong>根据 用户指定的配置对象来进行项目的编译</strong><br><strong>webpack是基于node创建出来的</strong><br><strong>默认在webpack 4.x的版本中,要打包的文件路径是 src->index.js->文件输出路径是dist->main.js</strong><br><strong>module.exports = {

// 注意:在webpack的配置文件中,mode选项是必须要有的

// 而且在开发阶段一定要配置成development模式

// 只有项目要上线了 才会配置成production 模式

    mode: 'production' // production(没有压缩过的文件) 产品 development(压缩过的文件) 开发

}} 

</strong>

5.在根目录中,新增一个src目录,并且 在src目录中 新建一个 index.js文件 作为webpack构建的入口;会把打包好的文件输出到 dist 自动建立一个 main.js

6.在终端中,直接运行 npm run dev (或者 npm run serve)启动webpack进行项目构建

 

实现webpack的实时打包构建

借助 webpack-dev-sever 这个工具,能够实现webpack的实时打包构建

运行 npm i webpack-dev-server -D 安装包

打开package.json文件,把scripts节点下的dev脚本,修改为如下配置

1

2

3

4

5

6

<strong>"scripts": {

    "test": "echo \"Error: no test specified\" && exit 1",

    "dev": "webpack-dev-server"

  },

 

</strong>

修改index.html文件中的 script的src,让src指向内存中根据目录下的../dist/main.js

<script src=”../dist/main.js”></script>

 实现webpack的实时打包构建

借助于webpack-dev-sever这个工具,能够实现webpack的实时打包构建

运行 `npm i webpack-dev-server -D` 安装包

打开package.json文件,把scripts节点下的dev脚本,修改为:

"scripts": {

    "test": "echo \"Error: no test specified\" && exit 1",

"dev": "webpack-dev-server"

 

 

 

使用html-webpack-plugin插件配置启动页面

1、装包 npm i html-webpack-plugin -D

2、在webpack.config.js中,导入插件

 

1

2

3

4

5

6

7

8

9

<strong>// 导入 html-webpack-plugin,从而帮我们自动把 打包好的 main.js 注入到 index.html 页面中

// 同时,html-webpack-plugin 可以把 磁盘上的 index.html 页面,复制一份并托管到 内存中;

const HtmlPlugin = require('html-webpack-plugin')

const htmlPlugin = new HtmlPlugin({

  // 传递一个配置对象

  template: './src/index.html', //(要复制哪个文件,需要给定一个路径) 指定路径,表示 要根据哪个物理磁盘上的页面,生成内存中的页面

  filename: 'index.html' //(生成新文件的名称 默认会把生成的新文件存放到根路径中,生成的文件也是虚拟的,看不见) 指定,内存中生成的页面的名称

})

</strong>

   

1

<strong>htmlPlugin 的两个功能:</strong><br><strong>  1.把template指定的模板页面 复制一份 当做虚拟index.html存放到项目的根目录中</strong><br><strong>  2.把打包好的 main.js注入到 index.html页面中 ,就不需要手动的引入 main.js文件了</strong>

3、把创建好的htmlPlugin对象,挂载到 plugins数组中

 

1

2

3

4

5

6

7

<strong>// webpack 这个构建工具,是基于 Node.js 开发出来的一个前端工具

module.exports = {

  mode: 'development', // 当前处于开发模式

  plugins: [htmlPlugin] // 插件数组

}

 

</strong>

   

实现自动打开浏览器、热更新和配置浏览器的默认端口号 记得写在package.json文件的 dev中

--open 自动打开浏览器

--host 配置IP地址

--port 配置端口号

--hot 热更新;最新的代码,一打补丁的形式 ,替换到页面上 加快编译的速度

--progress 展示编译的进度

--compress 对网络中传输的文件进行压缩,提高传输效率

"scripts": {
     "test": "echo \"Error: no test specified\" && exit 1", 
    "dev": "webpack-dev-server --open --port 80 --hot",
     "build": "webpack" 
},

 

 

 

 

ES6 模块化

CommonJS的导入和导出

module.export = {导出的对象} // 导出
let {flag} = require('文件路径')  // 导入

 

 

默认导入(import)的语法:

1

<strong>方法一: 把文件中的所有内容导出<br>import  接收名称 from ‘ 模板名称’  // 如: jQuery<br>import jQuery from 'jQuery'<br>方法二: 导出指定的方法或者参数<br>import {参数或者方法,....} from '模板名称'<br>import { method,....} from '模板名称'<br>方法三: <br>import * as 自定义名称 from '模板名称'<br>import * as aaa from '模板名称'</strong>

默认导出的语法:注意: 默认导出的成员,在使用import 导入的时候, 可以使用任意合法的成员名称来接收

export default { /*要导出的成员,多个用逗号隔开*/}

注意:在一个模块中,只能使用唯一 一次 export default{} 一个以上就会报错

 

按需求导入(import)和导出(export)

按需导入语法:

import { 成员名称 } from '模块名称'

如果要给导入的文件重命名 不要用 “ :” 要用as

按需导出语法:

方法一:
export var a = 10
..........
方法二:
export {a,.......}

 

 export default 与 export的区别

  1、export与export default均可用于导出常量、函数、文件、模块等
  2、你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用
  3、在一个文件或模块中,export、import可以有多个,export default仅有一个
  4、通过export方式导出,在导入时要加{ },export default则不需要

 

 

如果是HTML文件 在引入 JS 文件时, 给 script 加一个 type="module" 这样就不会出现变量名重复定义

 <script src="./bbb.js" type="module"></script>
 <script src="./aaa.js" type="module"></script>

上述引用 如果直接调用其中的参数 会出现下列错误

 

 

 

打包处理非js文件

使用webpack打包css文件

运行 cnpm i style-loader css-loader -D

打开 webpack.config.js 配置文件,在 module -> rules 数组中,新增处理 css 样式表的loader规则:

1

2

3

4

5

6

7

<strong>module: {

// 所有 非.js 结尾的第三方文件类型,都可以在 module 节点中进行配置

// rules 是匹配规则,如果 webpack 在打包项目的时候,发现,某些 文件的后缀名是 非 .js 结尾的

// webpack 默认处理不了,此时,webpack 查找 配置文件中的 module -> rules 规则数组;

rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }

 

</strong>

  

使用webpack打包less文件

运行 cnpm i less-loader less -D

在 webpack 的配置文件中,新增一个 rules 规则来 处理 less 文件:

1

2

3

<strong>{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }

 

</strong>

  

使用webpack处理css中的路径

运行 cnpm i url-loader file-loader -D

在 webpack 的配置文件中,新增一个 rules 规则来 处理 图片 文件:

1

2

3

4

5

<strong>// ?limit:只有小于limit大小的图片,才会被转为 base64单位是字节   

{ test: /\.jpg|png|gif|bmp$/, use: 'url-loader' }

Bype{ test: /\.jpg|png|gif|bmp$/, use: 'url-loader?limit=字节' }

 

</strong>

  

使用babel处理高级JS语法

之前说过,webpack 默认能够打包处理一些ES6中的高级语法;但是,webpack 并不能处理所有的高级ES6、ES7语法;

运行两套命令,去安装相关的 loader:

运行 cnpm i babel-core babel-loader babel-plugin-transform-runtime -D

运行 cnpm i babel-preset-env babel-preset-stage-0 -D

添加 babel-loader 配置项:

1

2

3

4

5

6

7

<strong>// 注意:在配置 babel-loader 的时候,一定要添加 exclude 排除项,把 node_modules 目录排除

// 这样,只让 babel-loader 转换 程序员 自己手写的 JS 代码;

// 好处:1. 能够提高编译的转换效率; 2. 能够防止不必要的报错!

{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }

在项目根目录中,添加 .babelrc 配置文件:

{ "presets": ["env", "stage-0"], "plugins": ["transform-runtime"]}

</strong>

 

在项目开发中,不会让腻手动配置    

先装一个npm i vue-cli -g 的全局包

在安装Vue init webpack项目名称 (没有引号)

会自动生成(下载)所有模板  第1个到 第7个都是 默认安装 第八个和第九个不装

就会自动安装好上边的所有配置  安装好后既可以在src 中写代码了

 

 

 

在webpack中安装和配置vue

运行npm i vue -S 把vue安装到项目依赖中

在index.js中使用import导入 vue模块

 

1

2

<strong>import vue from ‘vue’

</strong>

 

在index.html中创建将来要被vm实例控制的div 

 基于webpack的vue项目中,按照如上操作会报错

  1. 是因为使用import导入的vue 模板,导入的并不是功能最全的vue包,而是删减版的
  2. 删减版的vue包中功能很少,目的是为了减小vue的体积,因为文件越小,网络请求越快
  3. 想要让import导入最全的vue包 把import vue from ‘vue’,改成 import from ‘vue/dist/vue.js’

注意:在学习阶段可以再试使用import最全的vue包 开发是一定要用删减版的

 

 模块化和组件化的概念

  http://mint-ui.github.io/#!/zh-cn mint-ui 基于Vue.js 的移动端组件库

  https://element.eleme.cn/2.0/#/zh-CN  Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库

 模块化:是从代码的角度分析问题,把可以复用的代码 抽离为单独的模板 

      模块化的好:提供模块作用域的概念 防止全局污染

      提高代码的复用率 方便程序员之间的代码共享

组件化:组件化是从网页UI的角度进行分析问题的,把网页中可以复用的UI结构 抽离为单独的组件

    组件化的好处: 方便 UI 结构的重用

    随着项目的开发的深入,手中可用的组件会越来越多

    可以直接使用第三方封装好的组件库

    组件化能够让程序员更专注于自己的业务逻辑

 注意:每个组件必须有唯一的根元素进行包裹

 

简单来说就是: 我们将一个完整的页面分成很多个组件

        每个组件都用于实现页面的一个功能块

        而每个组件又可以进行细分

注册组件的基本步骤

  1. 创建组件构造器

    调用 Vue.extend()方法创建组件构造器

  2. 注册组件

    调用Vue.component()方法注册组件

  3. 使用组件

    在vue实例的作用范围内使用组件

 

 以上俩个都可以

 

定义全局组件

语法: Vue.component(‘组件的名称’,{组件的配置对象})

例:
// 组件名称最好是my-名称
Vue.component('my-com1',{
// 通过template属性,来指定当前组件的UI结构 template: '<div>这是自定义组件 my-com1</div>' })

 

 

 

在组件的配置对象中,使用template属性指定当前组件要渲染的模板结构

使用组件的语法

把 组件名称 以标签的形式 引入到页面是上 就可以了 (记得把组件名称添加到<div id=”app”>里面)

例:
<div id="app"> <my-com1></my-com1> </div>

 

 

 

注意:

  从更抽象的角度来说,每个组件就相当于是一个 自定义的元素

  组件中的DOM结构 且只能有唯一的根元素 进行包裹, 下面的会报错(在template属性里面只能有唯一的元素包裹)

例: Vue.component('my-com1',{ template: '<div>这是自定义组件 my-com1</div><p>捣乱的</p>' })

 

 

组件中定义 data 数据  methods方法  以及生命周期函数

可以认为: 组件是特殊的vue 实例

组件和实例 的 相同和区别

  1. 在组件中的data必须是一个function并且return 一个对象出去;在vue实例中 data既可以是一个对象,也可以是方法
  2. 在组件中,直接通过template属性来指定组件的UI结构
  3. 而在vue实例中,通过el属性指定实例控制的区域,但在实例中也可以通过template指定

Vue.compotrmt('my-com1',{ template:' <div>这是自定义组件my-com1</div> ', data:function() { rentrn {
    msg:'hello'
    } } }

 

为什么组件中的data属性必须定义为方法并且返回一个对象

在组件中的data属性必须定义为一个方法并返回一个对象

因为这样 能够保证每次创建的组件案例 都是自己的一块唯一的数据内存,防止组件之间数据的干扰

 

使用components 属性定义私有的子组件

在每个实例中,和 el data methods filters 平级 可以使用components属性,注册当前实例的私有子组件

和vue.component( ) 注册的全局组件不同 私有组件 只能在当前实例控制的区域内使用(其余用法都一样)

components:{ '组件名称':配置对象 }

 

 

 

 

以.vue为后缀名的文件夹的结果说明

每个.vue 文件 都是一个vue组件 他有三部分组成

template 写结构

script 行为样式

style 写样式结构的

Visual Studio Code要想有提示必须要安装这两个插件

 

在webpack中配置 .vue 组件网页的解析

  1. 运行 npm i vue-loader vue-template-compiler -D
  2. 在添加webpack.config.js文件中的 rules节点上添加匹配规则

{test:/\.vue$/,use:’vue-loader’}

 

  1. 在webpack.config.js中导入并配置插件

//导入插件

const VueLoaderPlugin = require('vue-loader/lib/plugin')

// new 一个插件的实例对象

const vuePlugin = new VueLoaderPlugin()

// 把 new 出来的插件实例对象,挂载到 `plugins` 节点中:

plugins: [...其它插件, vuePlugin]

 

导入并使用 .vue 组件的两种方式

全局注册 .vue 文件:

在 index.js 中导入 .vue 组件

使用 Vue.component() 把导入的 .vue 组件,注册为全局组件

 

私有注册 .vue 文件:

定义两个独立的组件 a.vue 和 c.vue

在 a.vue 组件中,导入 c.vue 文件,并使用 a.vue 组件的 components 属性,把 c.vue 注册为自己的私有子组件

复制代码

复制代码

//1. c.vue中导入 a.vue
import aaa from 'a.vue'
export default {
  //2. 通过 components 注册私有子组件
  components: {
    // 标签名 : 导入的文件
    'my-comcc' :aaa
  }
}
3. 把注册的私有组件名称,以标签形式 引入到自己的UI结构中(把注册的私有组件以标签的形式放到页面上去)
4. 在index.js引入c.vue 注册为全局组件
  import bbb from 'c.vue'
  Vue.component('组件名称': bbb)5.把index.js 中的全局组件名称以标签的形式放到 index.html 中

复制代码

复制代码

 

组件之间的数据通信

 父组件向子组件传递数据

复制代码

复制代码

创建好父组件和子组件
1. 父组件先要导入 子组件 ,把子组件挂在到父组件的私有组件中
  import 自定义组件名 from '子组件'
2. 在 index.js 导入父组件
  import 自定义组件名 from '父组件'
  注册父组件为全局组件
  Vue.component('组件名': 自定义组件名)
3. 在父组件中的 data 中的数据传给子组件, 子组件中用与data平级 的props:['父组件穿过来的值'] 接收
    props 表示 父组件传递到子组件的数据(只负责接收值)
4. 接收的的值可以直接用 {{父组件传过来的值}} 显示在子组件中
  注意: 父组件向子组件传值 用的是属性绑定,父组件绑定的属性名称是什么,那么子组件必须严格按照父组件规定名称来接收

 

子组件接收的的数据,也可以用 this 来接收;(上图接收到的值 可以直接用 this.msg 转存)
不要轻易修改接收到的父组件穿过来的值 要保证 props中 接收到数据的原装性;
要想修改的话 把接收到的值转存到 data 中,然后直接修改 data中的数据;

注意: 默认情况下,父组件中的数据是私有的,子组件无法直接访问
   父组件传递过来的数据,必须先要使用props 定义和接收之后,子组件才能使用

如果接收的是对象 会有迭代 用 lodash 可以解决
  安装: npm i lodash -S 安装包
  导入到需要用到的lodash的地方
  improt _ from 'lodash'
  用法: 文档 https://lodash.com/docs/4.17.11
  _.cloneDeep(obgects) // 深拷贝

复制代码

复制代码

步骤说明: 

① 父组件通过 属性绑定的方法,  把需要传递的值绑定到 子组件上

<son :msg="fMsg"></son>

② 子组件通过 props 来接收 就可以了

props: ['fMsg']

 

 

 

 

props数据验证

 props除了数组之外, 我们也可以使用对象, 当需要props进行类型等验证时, 就需要对象的写法了

验证支持的数据类型有: String、Number、Boolean、Array、Object、Date、Function、Symbol

type: 声明这个参数可以接收的数据类型

default 表示父组件未传入参数时,变量的默认值

required: 声明这个参数是否必须传入

validator:  当校验规则很复杂,默认提供的校验规则无法满足的时候可以使用自定义函数来校验。

复制代码

复制代码

 

  // 接收父组件穿过来的值

  props: {

    // fooA只接受数值类型的参数

    fooA: Number,

    // fooB可以接受字符串和数值类型的参数

    fooB: [String, Number],

    // fooC可以接受字符串类型的参数,并且这个参数必须传入

    fooC: {

      type: String,

      required: true

    },

    // fooD接受数值类型的参数,如果不传入的话默认就是100

    fooD: {

      type: Number,

      default: 100

    },

    // fooE接受对象类型的参数

    fooE: {

      type: Object,

      // 当为对象类型设置默认值时必须使用函数返回

      default: function () {

        return { message: 'Hello, world' }

      }

    },

    // fooF使用一个自定义的验证器

    fooF: {

      validator: function (value) {

        return value >= 0 && value <= 100;

      }

    }

  }

复制代码

复制代码

props中的驼峰标识

父组件向子组件传递值的时候最好不要使用驼峰标识 那样会报错 最好使用 myName => my-name

子组件接收的时候可以使用驼峰标识()

https://cn.vuejs.org/v2/guide/components-props.html#Prop-%E7%B1%BB%E5%9E%8B

 

 

父组件向子组件传递普通数据

在父组件中,以标签形式使用子组件的时候,可以通过属性绑定,为子组件传递数据

<my-son :pmsg1="parentMsg" :pinfo="parentInfo"></my-son>

在子组件中,如果向用父组件传递过来的数据,必须先定义 props 数组来接收:  props是与data 、el 平级的,是用来接收父组件传递过来的数据的

<script> export default { data(){ return {} }, methods: {}, // property 属性     // 注意:父组件传递到子组件中的数据,必须经过 props 的接收,才能使用; // 通过 props 接收的数据,直接可以在页面上使用;注意:不接受,不能使用外界传递过来的数据 props: ['pmsg1', 'pinfo'] } </script>

 

接收完的props数据,可以直接在子组件的 template 区域中使用:

<template> <div> <h3>这是子组件 --- {{pmsg1}} --- {{pinfo}}</h3> </div> </template>

 

注意:默认情况下 符组件中的数据 是私有的,字组件无法直接访问 ;要在子组件里添加一个 props 一数组的形式 接收父组件的数据

props 表示 父组件传递到子组件中的数据

注意: 父组件传递过来的数据,必须使用props定义和接收之后,子组件才能使用

父组件通过属性绑定,可以为子组件传递数据, 父组件绑定的属性名称是什么,那么 子组件必须严格按照父组件规定的名称来接收数据

props接收到的数据,可以直接在页面上使用

vue中的props接收到的数据,都是只读的, 今后 如果想要修改props中的数据,必须在data上线转存一份数据,然后直接操作data中转存的数据

 

7.2 父组件向子组件传递方法

如果父向子传递方法,需要使用 事件绑定机制:

<my-son @func1="show"></my-son> // @func1  属于自己定义的

其中,为 子组件传递的 方法名称为 func1, 具体的方法引用,为 父组件中的 show 方法

子组件中,可以直接通过 this.$emit() 方法 来触发父组件为子组件绑定的事件;

this.$emit('事件名称',要传递的数据)

在触发事件的同时 还可以通过第二个参数,传参回父组件中

 

想要深拷贝 要使用到 lodash 安装方法:

  1. npm i lodash -S     

2. 在直接调用就可是使用了 _.cloneDeep()  深拷贝

 

7.3 子组件向父组件传值

   什么时候需要使用自定义事件: 

  ①当子组件需要向父组件传递数据时, 就要用到自定义事件

  ②v-on不仅可以用于监听DOM事件, 也可以监听自定义组件之间的自定事件

 自定义事件的流程:

  ①在子组件中通过$emit() 来触发事件

  ②在父组件通过 v-on 来监听子组件事件

  子向父传值,要使用 事件绑定机制@;

       父向子传递一个方法的引用

      子组件中,可以使用 this.$emit() 来调用父组件传递过来的方法

      在使用this.$emit()调用 父组件中方法的时候,可以从第二个位置开始传递参数;把子组件中的数据,通过实参,传递到父组件的方法作用域中;

      父组件就可以通过形参,接收子组件传递过来的数据;

  this.$emit('要传递的事件名称','要传递的参数')

 

 

7.4 兄弟组件之间传值

 

发数据的一方用 JS文件夹名.$emit( '事件名称', 要发送的数据) 发送数据  接收的一方用 JS文件夹名.$on('事件名称' , function(){ 接收的数据 }) 接收数据

注意:兄弟组件之间,实现传值,用到的技术,是 EventBus

 

创建一个公共的js文件夹  这个js文件夹本质上就是一个vue实例对象

import Vue from 'vue' // 导入 Vue export default new Vue() // 把vue 暴露出去

俩个兄弟文件同时导入公共的js文件夹

import 自定义名称 from '公共文件'

在数据发送方,调用 自定义名称.$emit('事件名称' , '数据')  触发某个事件 从而发送数据

export default { data() { return { GGMsg: '这是GG的数据' } }, methods: { sendMsgToDD() { bus.$emit('ooo', /* 要发送的数据 */) } } }

在数据接收方,通过 自定义名称.$on()方法,自定义一个事件,只要有人触发了这个自定义事件,必然会调用指定的处理函数

在需要接收数据的兄弟组件中的 created 生命周期函数里,

使用 自定义名称.$on('事件名称', 处理函数(接收的数据) => {}) 自定义事件:

created() { // 通过 bus 的 $on 方法,可以为实例对象,绑定 自定义事件; bus.$on('ooo', data => {
    // 把接收到的数据 绑定到自己的 data 上 this.msgFromGG = data }) }

 Vue实例对象上有两个方法.$emit 和.$on 这两个是配合使用的

  Vue实例.$emit 是用来触发事件的   Vue实例.$emit('要被触发的事件', 要传递的数据)

  Vue实例.$on 是用来注册事件的   Vue实例.$on('触发的事件名称', (data) => { })   // data是 事件触发者传递过来的数据 

 

 

 

使用 this.$refs 来获取元素和组件

把要获取的DOM元素,添加 ref 属性,创建一个DOM对象的引用,指定的值,就是引用的名称:

// 子组件标签
<cpnref="myElement11">大家好</cpn>

如果要获取 某个引用所对应的 DOM对象,则直接使用 this.$refs.引用名称

默认情况下this.$refs 是空对象

 methods: {

        btnClick() {

          console.log(document.getElementById('myh1').innerHTML) // 结果是 大家好

          console.log(this.$refs.myElement11.innerHTML) // 结果是 大家好

        }

      },

也可以使用 ref 为组件添加引用;可以使用 this.$refs.组件应用名称, 拿到组件的引用,从而调用组件上的方法 和 获取组件data上的 数据;

只要通过 ref 拿到了 组件的引用对象 就可以直接通过 组件的引用对象, 调用组件 methods中的方法,或修改组件data中的数据

<h1 id="myh1" ref="mytest2">hello,大家好,我是咕天乐</h1>

const dom = document.getElementById('myh1')

console.log(this.$refs.mytest2 === dom)  // 结果是 true

 

使用 this.$parent查找当前组件的父组件。

使用 this.$children查找当前组件的直接子组件,可以遍历全部子组件, 需要注意 $children 并不保证顺序,也不是响应式的。

使用 this.$root查找根组件,并可以配合$children遍历全部组件。

使用 this.$refs查找命名子组件。

 

父组件访问子组件: 使用this.$children或者this.$refs

  直接使用this.$children children是一个复数 访问的不止一个, 所以他返回的是一个数组 组件集合

  使用$refs

    给子组件添加ref属性

<cpn ref="cpnClick"></cpn>

子组件访问父组件: 使用this.$parent

// 直接在子组件中直接打印
console.log(this.$parent)

 访问根组件 $root

    cpnClick() {
              console.log(this.$root);
            }
 

 

使用 霸道的 render 函数渲染组件

如果在 vm 实例中既指定了 el 又指定了 render 函数,则会把 el 所指的的区域,替换为 render 函数中所提供的组件;

既然 render 函数会替换到 el 区域内的所有代码,也会让 template 属性失效;因此,在删减版的 vue 包中,new 出来的 Vue 实例对象,不允许 挂载 data 属性和 template 属性!

 

当时用 render 渲染指定组件的时候,VM实例对象中的data 和 template 都没有任何意义了

复制代码

复制代码

// render 是和el,data 平级的函数 可以把指定的页面,渲染到index.html 中 
render:function(createElement){ // createElement 形参是一个方法,作用是: 把指定组件,渲染出来,并替换 el/template 所指区域 
  return createElement(要渲染的组件) 
}
也可以这样写:
render: createElement=>createElement(要渲染的组件)

// 普通用法 createElement('标签',{标签属性},[标签中的内容])

复制代码

复制代码

 

 

SPA(Single Page Application)单页应用

锚链接及常规的url 的区别

  1. 普通的URL地址,会刷新整个页面,会追加浏览器的历史记录
  2. 锚链接 不会触发页面的整体刷新,会追加浏览器的历史记录(锚链接是在页面内的跳转)

 

SPA概念定义: SPA英文全称是 single page application  中文翻译是”单页面应用程序”

通俗的理解是:  zhiyou yige WEB 页面的网站。网站的所有功能都在这个唯一的页面上进展与切换

 

Spa的特点:

  1. 整个网站只有一个页面
  2. 浏览器以开始请求这个页面,必须加载对应的HTML CSS JavaScript
  3. 用户的所有操作,都在这唯一的页面上完成
  4. 页面数据都是用ajax 请求回来的

Spa好处:

实现了前后端分离开发,各司其职。提高了开发效率

用户体验好、快,内容的改变不需要重新加载整个页面

Spa的缺点:

对SEO(搜索引擎优化)不是很友好,因为页面数据是ajax渲染出来的

刚开始的时候加载速度可能比较慢,

页面复杂度比较高,对程序员能力要求较高

 

使用<component>标签实现组件切换

component 是有vue官方提供的,作用 就是根据 is属性指定的名称,来展示指定的组件

1. 把需要展示的组件导入

2. 注册为私有组件

3. 在data中创建一个属性, 把需要默认展示首页的组件标签名称填入

<component>是vue提供的,作用是 把 :is 指定的组件名称 渲染到 <component> 内部

身上有一个 :is 属性

可以把component 标签理解为占位符 值是什么名称 就会展示什么名称组件

单页面应用程序中,实现组件切换的根本技术就是监听window.onhashchange事件(在created使用)

// 可以拿到地址栏中 #后边的hash值 (可以在后台 自己拿一下看看)
// 用这个的时候 推荐使用 switch
// 这是原生的方法
  window.location.hash //http://www.w3school.com.cn/js/js_window_location.asp

 

 

 

 

路由

路由就是对应关系

  1. 后端路由的定义:URL地址到后端处理函数之间的关系
  2. 前端路由的定义:hash到组件之间的对应关系
  3. 前端路由的目的:为了实现单页面应用程序的开发
  4. 前端路由的组成: ① 链接 ②组件 ③链接与组件之间的对应关系

 

在vue中使用vue-router

安装导入并注册路由模块

 运行 npm i vue-router -S 安装路由模块

 在index.js中导入并注册路由模块

// 导入路由模块 import VueRouter from 'vue-router' // 注册路由模块(把路由安装到 Vue 上) Vue.use(VueRouter)

 

创建路由链接 

<!-- router-link 就是 第一步,创建 路由的 hash 链接的 -->
<!-- to 属性,表示 点击此链接,要跳转到哪个 hash 地址, 注意:to 属性中,大家不需要以 # 开头 -->
<router-link to="/home" tag="li">首页</router-link>
<router-link to="/movie">电影</router-link>
<router-link to="/about">关于</router-link>
tag 属性 要渲染成什么标签 默认 是 a标签 tag可以转换成自己想要的标签

创建并在index.js 中导入路由相关的组件 

import Home from './components/Home.vue' import Movie from './components/Movie.vue' import About from './components/About.vue'

创建路由规则 

复制代码

复制代码

    // 创建路由对象 前端路由: hash 值 到组件的对应关系 一个hash 对应一个要展示的组件 
    // 创建路由规则(对应关系)
    // 配置对象中要提供hash 地址到组件之间的 对应关系
    const router = new VueRouter({
      // routes 是路由规则数组,其中的每个对象 都是一天路由规则 
      routes: [
        // 这个 routes 就是 路由 规则 的数组,里面要放很多的对应关系
        //路由规则的基本组成 { path: 'hash地址', component: 配置对象(要展示的组件) },在path中 ,带冒号的,是路由参数项
           // 通过 redirect是属性,可以实现前端路由的重定向 
           { path: '/', redirect: '/home' },
        // 如果访问的是 根路径 就会跳转到指定路径 
        { path: '/home', component: Home },
        { path: '/movie', component: Movie },
        {
          path: '/about', component: About,
          children: [ // 子路由
            path: '/',
            component: ''
          ]
        }]
    })
    // 创建的 router 对象,千万要记得,挂载到 vm 实例上 
    const vm = new Vue({
      el: '#app',
    render: c => c(App),
    router: router
      // 把 创建好的路由对象,一定要挂载到 VM 实例上,否则路由不会生效
    })

复制代码

复制代码

 

在页面上放路由内容 

<!-- 这是路由的容器,将来,通过路由规则,匹配到的组件,都会被展示到这个 容器中 --> <router-view/>

使用 

// 在 app.vue中使用 router-link

// <router-link> 标签 将来会被 默认 渲染为 a 链接
// to 属性 表示 点击这个链接 要跳转到哪个 hash 值 to 相当于 href
// 展示的地址要和 path 对应上 <router-link to="/地址"></router-link>
// router-view 这是一个占位符 将来通过 路由规则 匹配到的组件 会被替换到router-view所在的位置 <router-view/>

  

路由规则的匹配过程

1. 用户点击 页面的 路由链接router-link,点击的一瞬间,就会修改 浏览器 地址栏 中的 hash 地址;   router-link标签,将来会被默认渲染为 a 链接   to属性 表示点击这个链接要跳转到哪个hash值
  redirect 重定向 2.当 hash 地址被修改以后,会立即被 vue-router 监听到,然后进行 路由规则的 匹配;最终,找到 要显示的组件; 3. 当 路由规则匹配成功以后,就找到了 要显示的 组件,然后 把 这个组件,替换到 页面 指定的 路由容器router-view 中 4. router-view这是一个占位符,将通过路由规则 匹配到组件,会被替换到 router-view 所在的位置 只要是路由组件必须要有占位符

 

 

设置路由高亮的两种方式

  1. router-link 有一个 router-link-active 类名
  2. 通过路由默认提供的 router-link-active 类名,为这个类添加自己的高亮样式即可
  3. 通过路由构造函数,在传递路由配置对象的时候,提供linkActiveClass属性,来覆盖原有的高亮样式

  与routers平级中有一个linkActiveClass , 这个的意思是: 被激活的路由类名,默认是router-link-active,想要修改只要在这个里面输入 要被修改成什么 就可以( 简单来说就是: 这个对象是 指定代码高亮的样式的 )

 

嵌套路由(子路由)

  1. 在对应的路由组件中,新增 router-link 路由链接
  2. 创建 router-link 对应要显示的组件
  3. children属性 是数组,表示子路由 是routes第三个参数
  4. 在对应的路由规则中,通过 children属性,定影子路由规则

 

{ // redirect 重定向 path: '/movie',
component: Movie,
redirect: '/movie/in_theaters', // 指定子路由规则 children: [ { path: '/movie/in_theaters', component: In_theaters }, { path: '/movie/coming_soon', component: Coming_soon } ] }

在router-link之下 添加router-view容器组件
可以使用redirect 实现 嵌套路由的重定向
router-link 的to 属性,可以使用v-bind属性绑定 动态绑定一个路由地址
     tag 属性 要渲染成什么标签 默认 是 a标签
router-link 默认渲染为 a 链接,可以使用 tag 属性 强制router-link渲染为特定的标签(如: li <router-link tag="li" to="">)

 

路由传参

路由传参,首先,要把路由规则中,对应的参数位置,通过: 来定义为一个参数;

可以在组件中,直接使用this.$route.params.id 来获取参数;【写起来太麻烦,不推荐】

也可以开启路由的 props 传参,来接收路由中的参数;【推荐方式】

如果在组件中,想要拿到path 中匹配的路由参数项 可以为路由规则开启 props传参 (props:true)

在需要传参的路由规则中,添加 props: true 如下 : 

复制代码

复制代码

// 在路由规则中,可以把参数项的前面添加 :
// :id 表示要传入的参数 记得有 冒号 属性绑定
{ path: '/movie/:type/:id', component: movie, props: true } 在 对应的组件中,定义 props 并接收路由参数 const movie = { // 使用参数 template: '<h3>电影组件 --- {{type}} --- {{id}}</h3>', props: ['type', 'id'] // 接收参数 }

// 在需要使用的地方添加[不常用]
// 在页面直接打印 {{id}} 可以查看传递过来的参数
export default {
  props: [ 'id' ] // 接收的参数
}
// 在新页面 用 $route.params.参数名 也可以接收到传递的参数
// 在页面 使用 {{$route.params.参数名}} 可以查看传递过来的参数值

 

复制代码

复制代码

在.vue文件中,只要使用v-for 指令,必须要有 :key 属性

3.7 命名路由

命名路由是: 就是为路由规则,添加了一个 name ;

什么是命名路由

router-link中通过路由名称实现跳转

命名路由使用 params属性传参

routes: [{ path: '/login', component: login, name: moviePage }] // 通过命名路由,实现路由跳转
// name 是命名路由的名称对象
// 给他绑定一个对象 name 要去那个路由里边 params 传递的参数
<router-link :to="{ name: 'moviePage', params: {type: 'top250', id: item.id} }" tag="li" v-for="item in list" :key="item.id">
</router-link>
// 这是使用字符串拼接,得到的 路由地址 实现跳转 <router-link :to="'地址'+item.id" tag="li" v-for="item in list" :key="item.id"></router-link>

 

 

3.8 编程式(JS)导航  // https://router.vuejs.org/zh/guide/essentials/navigation.html

之前的router-link是标签跳转;除了使用router-link是标签跳转之外,还可以使用Javascript来实现路由的跳转;

编程式导航

使用vue-router提供的JS  API实现路由跳转的方式,叫做编程式导航;

编程式导航的用法 

// 如果要跳转指定的 hash地址, 只能使用push方法

this.$router.push('路径的地址') 如果要跳转到指定hash地址,只能使用push方法

this.$router.go(n)   n == -1 后退一步  n==1 前进一步

this.$router.forward() 前进一步

this.$router.back()  后退一步

以上的记得都要注册在methods 里 的方法里

methods: { // 在调用这个 goBack() { this.$router.go(-1) } }

 

 

 

 

this.$route 是 路由参数对象

this.$router 是路由导航对象

vm 实例上的 router 属性,是来挂载路由对象的

在 new VueRouter({ /* 配置对象 */ }) 的时候,配置对象中,有一个 routes 属性, 是来创建路由规则的

 

3.9 路由导航守卫

案例需求:只允许登录的情况下访问 后台首页 ,如果不登录,默认跳转回登录页面;

API语法:

// router.beforeEach()方法,会在每个路由规则被匹配之前 做一件事 // 参数1:是要去的那个页面 路由相关的参数 (表示 将要访问的那个路由对象) // 参数2:从哪个页面即将离开 (从哪个路由对象,跳转而来) // 参数3:next 是一个函数,就相当于 Node 里面 express 中的 next 函数 (代表放行) // 注意: 这里的 router 就是 new VueRouter 得到的 路由对象 router.beforeEach((to, from, next) => { /* 导航守卫 处理逻辑 */ })​
window.sessionStorage.getItem('token') // 获取 token字符串 window.sessionStorage.clear() // 清空当前所有缓存 https://developer.mozilla.org/zh-CN/docs/Web/API/Window/sessionStorage

 

复制代码

复制代码

// 引入路由导航 import Router from 'vue-router'
import login from '路由地址/login'
import home from '路由地址/home' // 创建路由 const router = new Router({
  routes: [
    {path: '/login', component: login},
    {path: '/home', component: home}
  ]
}) // 创建路由拦截器 // to 表示 去那个路由 // from 表示 从哪个路由而来 // next 表示 放行 router.beforeEach((to,from,next)={ // 判断语句
  // 如果是去login, 直接放行
  if(to.path === '/login') return next()
  // 如果去 home 要先判断是否有token字符串
  const tokenStr = window.sessionStorage.getItem('token')
  // 如果没有token 强制跳转到 login页面
  if(!tokenStr) return next('/login')
  // 有token直接放行
  next()
}) // 把路由对象暴露出去 export default router

复制代码

复制代码

 

 

4. watch 监听数据

watch 监听的特点:监听到某个数据的变化后,侧重于做某件事情;

  缺点: 只能监听一个数据的变化;

  watch是与el data平级的

只要被监听的数据发生了变化,会自动触发 watch 中指定的处理函数;

watch:{ password:function(newVal,oloVal,){ console.log(newVal) // 输入的新值 console.log()oloVal // 老值 }}​

 

5. computed 计算属性

计算属性特点:同时监听多个数据的变化后,侧重于得到一个新的值;

只要依赖的任何一个数据发生了变化,都会自动触发计算属性的重新求值;

计算属性,在定义的时候,需要被定义为function ,但是在页面UI结构中,计算属性是直接当做 普通属性来使用的 在计算属性中 必须return 一个返回值

 

 在 Vue 中,computed 的属性可以被视为是 data 一样,可以读取和设值,因此在 computed 中可以分成 getter(读取) 和 setter(设值),一般情况下是没有 setter 的,computed 预设只有 getter ,也就是只能读取,不能改变设值。

 

 

computed 和 methods 的区别?
1、相同点
如果作为模板的数据显示,二者能实现响应的功能,唯一不同的是methods定义的方法需要执行
2、不同点
computed 会基于响应数据缓存,methods不会缓存
diff之前先看data里的数据是否发生变化,如果没有变化computed的方法不会执行,但methods里的方法会执行

 

 

使用vue-cli 快速创建vue项目

首先安装 npm  i vue-cli -g  // 安装全局的vue 脚手工具

vue init webpack 项目名称 // 初始化项目

npm i  // 安装 vue所需要的包

npm run dev (npm run serve)// 运行终端(运行项目)

npm run build// 打包

 

自定义指令

全局自定义指令

概念:在全局任何组件中东可以被调用的自定义指令,就是全局自定义指令

语法:Vue.directive(‘全局自定义名称’,{/* 自定义指令配置对象 */})

自定义指令的名称,在定义的时候不需要加 v- 前缀,但是在使用的时候 必须加上 v- 前缀

Vue.directive('red',{ // 当指定被第一解析的时候,就会触发bind方法 // 此时 指令所绑定到的元素 还没有被插入父节点中 // 【推荐】在bind方法中,为指令所绑定到的元素设置样式相关的属性 bind:function(el,binding){ // el 指的是DOM元素 // binding 是指令所绑定的一些数据,其中,binding.value就是指令 =(等号) 后面的数据 // el.style.color = 'red'; el.style.color=binding.value } })

 


  

私有自定义指令

概念:只有指令所属的组件中,才可以被正常调用的指令,是私有自定义指令

语法:

// test1.vue 组件

<template></template>

 

<script>

    export default {

        directives: {

           //  '私有自定义指令名称': { /* 私有自定义指令配置对象 */ }

    bind: function(el) {

      el.style.background = 'red'

    }

        }

    }

</script>

 

指令配置对象中的 bind 和 inserted 的区别

bind 方法:

  1. 绑定当前指令的元素,在内存中被创建的时候就会被立即调用
  2. 推荐吧样式相关的设置,都定义在bind 方法中

Inserted方法:

  1. 绑定当前指令的元素,被插入到DOM树之后才会被调用
  2. 推荐把行为 相关的设置,都定义在inserted 方法中

想要查看bind和inserted 的区别 终端中打印 el.parentNode 即可

总结:在bind 中队员说的样式进行操作 ,在inserted 中 对元素的行为进行操作

 

插槽 slot

组件插槽是为了让我们封装的组件更加酷游扩展性

让使用者可以决定内部的一些内容到底展示什么

定义:定义子组件的时候,在子组件内部刨了一个坑,父组件想办法王铿里天内容

 

单个插槽(匿名插槽)

定义插槽:在子组件作用域中,使用 <slot></slot> 定义一个插槽;

使用插槽:在父作用域中使用带有插槽的组件时,组件内容区域中的内容,会插入到插槽中显示;

     如果在定义某个组件的时候,不太确定组件中的某一部分,具体显示什么UI元素,此时 可以把这个区域定义为一个占位符(插槽),今后,这个占位符中具体显示什么标签,是有使用者决定

谁使用这个组件,谁就可以为这个组件指定插槽中要渲染的UI结构,这个指定的UI元素,会被替换到<slot></slot>插槽的位置

使用的方法 :

  ①在组件中定义一个 <slot> 标签  

①基本使用
 直接定义一个 <slot>标签
② 默认值
在<slot>标签中写入默认的值
<slot><span>内容</span></slot>
注意: 如果在调用的slot标签中输入内容 会把默认值替换掉

  ②在标签中定义要展示的信息

复制代码

复制代码

// html部分
    <slot><button>按钮</button></slot>
    <slot><i>内容</i></slot>
    <slot><button>按钮</button></slot>


// 子组件部分
<template id="cpn">
  <div>
    <h6>我是子组件</h6>
    <slot></slot>
  </div>
</template>

复制代码

复制代码

显示结果

如果, 相同部分多次调用 可以在 slot 中直接写入当做默认值来使用

复制代码

复制代码

// HTML部分
<cpn></cpn>
<cpn><span>内容</span></cpn>
<cpn></cpn>
// 子组件部分
<template id="cpn">
  <div>
    <h6>我是子组件</h6>
    <slot></slot>
  </div>
</template>

复制代码

复制代码

显示的结果与上面的结果是一样的 

slot标签中如果有内容的话 会当做默认值使用

 

 

注意: 在一个组件中,只允许出现一个 匿名插槽

 

多个插槽(具有名字的插槽)

具名插槽的调用: 

  ①首先要把定义好的组件导入到需要使用的地方

import head from './slot/head'

  ②在把导入的组件定义到 components 中

components: {top: head}

  ③把定义好的名称 在页面中当做标签使用

    <top></top>

 

定义具名插槽:使用 name 属性为 slot 插槽定义具体名称;

<slot name="header"></slot> // header 自己定义的

 

使用具名插槽:在父作用域中使用带有命名插槽的组件时,需要为内容指定 slot="name" 来填充到指定名称的插槽;

<span slot="header"></span>

 

 

作用域插槽(常用)

官方给出的解释是: 父组件模板的所有东西都会在父级作用域中编译;子组件模板的所用东西都会在自己作用域中编译;

父组件替换插槽的标签, 但内容由子组件提供

定义作用域插槽:在子组件中,使用slot定义插槽的时候,可以通过属性传值的形式,为插槽传递数据。

例如:

复制代码

复制代码

 

  <div id="app">

    <cpn>

   <!-- .vue 2.5.x一下必须有template -->

      <template slot-scope="slot">

          {{slot.data}} // 拿到的数据是: [ "javascrpit", "typescript", "c++", "c#", "python" ]

      </template>

    </cpn>

  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <template id="cpn">

    <div>

      <slot :data="language">

        <ul>

          <li v-for="item in language">{{item}}</li>

        </ul>

      </slot>

    </div>

  </template>

  <script>

    var vm = new Vue({

      el: '#app',

      components: {

        cpn: {

          template: '#cpn',

          data() {

            return {

              language: ['javascrpit', 'typescript', 'c++', 'c#', 'python']

            }

          }

        }

      }

    });

  </script>

 

复制代码

复制代码

使用作用域:在父作用域中,通过定义 slot-scope=”slot”属性,接收并使用插槽数据为slot添加属性绑定,把插槽中需要渲染的数据传递给外界使用者

可以在使用组件的时候,通过定义slot-scope属性接收插槽传递出来的数据

注意: template 标签,只会起到包裹元素的作用,不会被渲染成任何标签元素

  在同一组件中 不同插槽的作用域 是独立的

 

 

 

安装和使用 element-ui

element-ui是 饿了么 前端团队 开源出来的一套Vue组件库

  1. 完整版引用 element-ui组件

运行 npm i element-ui -S 安装组件库

在main.js中 导入element-ui的包 配置样式表 并且安装到Vue上

// 导入 element-ui 这个包

import ElementUI from ‘element-ui’

// 导入 配套的样式表

import ‘element-ui/lib/theme-chalk/index.css’

//在把 element-ui 安装到 Vue 上

Vue.use(ElementUI )

 

 按需导入element的组件 

复制代码

复制代码

    import Vue from 'vue';
    import { Button, Select } from 'element-ui';
    import App from './App.vue';
    /*
    Vue.component(Button.name, Button);
     Vue.component(Select.name,Select); 
     */
    // 或写为 
    Vue.use(Button)
     //按钮样式 Vue.use(Select)
     // 弹出层 new Vue({ el: '#app', render: h => h(App) });
 

复制代码

复制代码

 

 


在在 webpack.config.js 文件中的 rules 添加一条配置样式 

{ test:/\.eot|ttf|woff|woff2$/,use:'url-loader'}

 

  1. 按需要导入和配置 element-ui

<divclass="p"> 运行 npm i babel-plugin-component -D 安装支持按需要导入的模块 <divclass="p"> babel-plugin-component 会根据你用了几个组件 ,按需要榜我们引入对应的CSS 样式 就不需要自己导入最全的样式了 <divclass="p">打开 .babelrc 配置文件 想改如下

复制代码

复制代码

{ "plugins": [
  "transform-runtime",
    [ // +好表示要添加的项
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ],
  "presets": [
  "env",
  "stage-0"
  ]
}

复制代码

复制代码

 

 

 

如果希望只引入部分组件 ,那么需要在 main.js中写入 如下内容 

 


ESlint 语法检查规范 ( 会出警告的可能情况 ) 

  1. 声明但是没有使用的变量会报错
  2. 空行不能连续大于等于 2
  3. 在行结尾处,多余的空格不允许
  4. 多余的分号 不允许
  5. 在方法名和形参列表的小括号之间,必须有空格
  6. 在单行注释的 // 之后 必须有一个空格
  7. 字符串要使用单引号 不能使用双引号
  8. 在每一个文件的结尾 都要有一个唯一的 空行   不然会有警告

 

模拟后台数据json-server

运行命令 npm i install json-server -D 全局安装 json-server

项目根目录创建 mock 文件夹

mock文件夹下添加 db.json 文件 自己所需要模拟的数据

{ "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } }

 

package.json 添加命令  打开package.json文件 在scripts节点中 新增一个 mock 的节点

"mock": "json-server --port 3333 --watch mock/db.json"

 

 打开终端 运行 npm run mock 运行 json-server服务器

faker.js 创建假数据

运行 npm i faker -D 安装生成假数据的包

运行 npm o lodash -S 安装 lodash,利用 _.times( ) 方法循环调用 faker生成数据

把mock 目录下的 db.josn 改名为 db.js

修改db.js 中的代码

复制代码

复制代码

// 导入 lodash 

    const _ = require('lodash')

    // 导入 faker 生成假数据

    const faker = require('faker')

    // 设置数据本地化 (把随机生成name改成中文)

    faker.locale = 'zh_CN'

    // 使用 CommonJS 规范把生成的数据导出;

    // 其中,module.exports 必须指向 函数,且函数中,必须 return 一个数据对象

    module.exports = () => { // json-server 要求最终 return 的数据,必须是一个对象;

      const data = { brandlist: [] }

      // 调用 _.times 随机 10 次生成假数据 

      data.brandlist = _.times(10, n => {

        return {

          id: n + 1,

          //使用索引你模拟Id 

          name: faker.random.word(), ctime: faker.date.recent()

        }

      })

      // 把生成的数据返回

      return data

    }

复制代码

复制代码

 

 

 


  

$nextTick() 方法的作用,就是当页面上的元素重新渲染之后,才会执行的 回调函数中的代码

 

使用Gzip 的好处:

如果服务器,启用Gzip,则文件在网络中 传输的时候,会被压缩;经过Gzip的压缩之后,文件的体积

 

CDN 就是 网速特别快的 一台服务器 (网址: https//www.bootcdn.cn)

 

转载:https://www.cnblogs.com/javalittlebird/p/12654753.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值