51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Vue笔记[二]-组件化

QX-AI
GPT-4
QX-AI初始化中...
暂无预设简介,请点击下方生成AI简介按钮。
介绍自己
生成预设简介
推荐相关文章
生成AI简介

生命周期 {#生命周期}

Vue会在一些特殊时刻去调用一些特殊的函数

这些要经过的特殊时刻就是生命周期 ,要调用的特殊函数就是生命周期函数(生命周期钩子,生命周期回调函数)

**为什么叫钩子:**vm在某个步骤上已经写了执行该名称的函数,但函数内容未定义,得程序员来定义。即生命周期函数的名字不可更改,但函数的具体内容需要程序员根据业务需求编写

Vue实例的生命周期:
1、初始化显示

  1. beforeCreate() => 初始化:生命周期、事件,但数据代理还未开始
  2. create() => 初始化:数据监测、数据代理
  3. beforeMount() => 模板解析完毕,虚拟DOM建立,但还未挂载
  4. mounted() => 挂载完毕,虚拟DOM转为真实DOM

2、更新状态: this.xxx = value

  1. beforeUpdate() => 数据已更新,但页面还未更新,新旧虚拟dom还未对比
  2. updated() => 数据和页面都是新的

3、销毁 vue 实例: vm.$destroy() 触发下面两个钩子

  1. beforeDestroy() => 此时vm上所有东西都是可用的,但不再解析模板更新页面
  2. destroyed() => vm彻底被销毁

还有三个钩子不在图中,和路由相关

常用钩子:

  1. mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
  2. beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】

关于销毁Vue实例:

  1. 在大多数场景中不应该调用 vm.$destroy() 。最好使用 v-if 和 v-for 指令以数据驱动的方式控制子组件的生命周期。
  2. 销毁后借助Vue开发者工具看不到任何信息
  3. 销毁后自定义事件会失效,但原生D0M事件依然有效
  4. 在beforeDestroy中做好善后工作

组件 {#组件}

组件: 应用中局部 功能代码资源集合

在 Vue 中,组件是可复用Vue实例

组件体现了封装的思想,组件也可以嵌套封装

组件化: 编写一套组件,在所需的页面引入组件,当应用中的功能都是多组件的方式来编写的, 这个应用就是一个组件化的应用

**为什么要组件化:**传统的三件套可以只能做到拆分css、js模块化,而html结构不复用,且文件依赖关系(N-1-N)复杂,组件化后,页面的每个部分都对应一个组件,组件中的小功能部分也能对应更多组件,组件逐层嵌套,最终由一个Vue实例管理,依赖关系清晰,通过引入组件构建页面,代码复用率高,后续维护也能针对性找到组件进行操作

非单文件组件 {#非单文件组件}

非单文件组件: 一个文件中包含n个组件,实际开发几乎不用这种写法

使用组件流程:

  1. 定义组件: Vue.extend()
    - 配置项中不能写el属性 ,因为最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器
    - 组件中的data必须用函数式 ,避免组件被复用时,数据存在引用关系。
    - 使用 template 配置组件模板结构,必须有一个根元素包裹

    |------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const school = Vue.extend({ // 模板,template中的模板必须有一个根元素包裹 template: ` <div> <h3>{{name}}</h3> <h3>{{city}}</h3> </div> `, // 组件中的data必须用函数式 // 因为对象是引用类型数据,函数式返回一个新对象才能保证多次引用组件的data互不影响 data() { return { name: '五道口', city: '京海' } } }) |

  2. 注册组件:
    - Vue.component() 全局注册
    - 局部注册,在vm配置项的 components 属性中

    |---------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // 全局注册组件,多个vue实例都能使用该组件 Vue.component('school', school) // 组件由vm管理 new Vue({ el: '#root', data: { msg: '信息' }, // 局部注册组件 components: { // 组件名 student } }) |

  3. 使用组件: 在容器中写组件标签

案例: 非单文件组件案例

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <div id="root"> <h2>{{msg}}</h2> <!-- 引用组件,组件标签 --> <school></school> <hr /> <!-- 多次引用组件,且数据独立互不影响 --> <student></student> <student></student> </div> <script> // 使用Vue.extend定义一个组件,传入一个配置项 const school = Vue.extend({ // 模板,template中的模板必须有一个根元素包裹 template: ` <div> <h3>{{name}}</h3> <h3>{{city}}</h3> </div> `, // 组件中的data必须用函数式 // 因为对象是引用类型数据,函数式返回一个新对象才能保证多次引用组件的data互不影响 data() { return { name: '五道口', city: '京海' } } }) const student = Vue.extend({ template: ` <div> <h3>{{name}}</h3> <h3>{{age}}</h3> <button @click="age++">年龄加一</button> </div> `, data() { return { name: 'chuckle', age: '19' } } }) // 全局注册组件,多个vue实例都能使用该组件 Vue.component('school', school) // 组件由vm管理 new Vue({ el: '#root', data: { msg: '信息' }, // 局部注册组件 components: { // 组件名 student } }) </script> |

注意事项 {#注意事项}

关于组件名:

  1. 组件名只有一个单词 时,引用组建时写小写 <student>大写 <Student> Vue只会去找小写的组件名,即组件名只有一个单词时 需使用小写

  2. 组件名由多个单词 组成时,有两种写法:横杠写法双驼峰写法 (只能在脚手架环境中使用)

    |---------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 | <!-- 横杠写法 --> <my-school></my-school> <script> Vue.component('my-school', MySchool) </script> <!-- 双驼峰写法(只能在脚手架环境中使用) --> <MySchool></MySchool> <script> Vue.component('MySchool', MySchool)o[] </script> |

  3. 不能使用html已有标签名作为组件名

  4. 在定义组件时添加 name 配置,无论注册使用时是什么名,在开发者工具中显示的都是该 name(首字母同样会自动显示大写)

    |---------------------------|--------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 | const school = Vue.extend({ // 设置 name name: 'MySchool', template: ``, data() { return {} } }) |

脚手架环境 下,可以使用组件时可以写双标签 <school></school>自闭合标签 <school/>,不用使用脚手架时,<school/> 会导致后续组件不能渲染。

定义组件可以简写:
注册组件时底层有判断,若是一个对象,Vue会帮我们调用Vue.extend,并将对象作为配置项传入

|---------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // 简写,实际上也调用了Vue.extend const school = { template: ``, data() { return {} } } // 写上 Vue.extend 不简写 const school = Vue.extend({ template: ``, data() { return {} } }) |

组件嵌套 {#组件嵌套}

组件嵌套: 一个组件也会用到其它多个组件,组件关系逐层嵌套,形成父子组件关系

使用方式: 在父组件中 components 配置项注册其子组件,组件在哪注册就要在哪使用

开发中的技巧: 定义一个名为 app 的组件,用于管理页面中最上层的所有组件,而 vm 本身只管理 app 组件

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <div id="root"></div> <script> // 子组件的定义要放到父组件前 const student = { template: ` <div> <h3>学生姓名:{{name}}</h3> <h3>学生年龄:{{age}}</h3> </div> `, data() { return { name: 'chuckle', age: '19' } } } // 定义父组件 const school = { // 在父组件中使用子组件 template: ` <div> <h2>学校名:{{name}}</h2> <hr /> <student></student> </div> `, data() { return { name: '五道口' } }, // 注册子组件 components: { student, } } // 定义一个欢迎语组件,和school组件同级 const hello = { template: ` <div> <h3>{{welcome}}</h3> <hr/> </div> `, data() { return{ welcome: '欢迎!' } } } // 定义app组件,管理所有组件 const app = { template: ` <div> <hello></hello> <school></school> </div> `, // 管理下一层的父级组件 components: { school, hello } } new Vue({ el: '#root', // 应用app组件,替换掉root容器 template:`<app></app>`, components: { // vm只管理app组件 app } }) </script> |

VueComponent构造函数 {#VueComponent构造函数}

每个组件的本质 都是一个 VueComponent() 构造函数,它由 Vue.extend() 生成并返回

每次调用 Vue.extend() ,返回的都是一个全新的 VueComponent() 构造函数

打印app组件:

|-------------------|-----------------------------------------------------------------------------------| | 1 2 3 4 5 | const app = Vue.extend({ template: ``, components: {} }) console.log(app) |

输出

|---------------|----------------------------------------------------------| | 1 2 3 | ƒ VueComponent(options) { this._init(options); } |

既然是构造函数,使用它就需要 new 创建实例
只需要在合适的位置写 <school></school> ,Vue 在解析模板时 会自动去创建对应的VueComponent 构造函数的实例

即Vue会在解析模板自动执行new VueComponent(options)

1、this的指向:
(1) Vue.extend(options) 组件配置中,this 指向 VueComponent 实例对象
(2) new Vue(options) 配置中,this 指向 vm 实例对象

2、Vue对组件的关系设计:

  1. 每种 组件定义时都需要调用 Vue.extend() ,它返回一个新的 VueComponent() 构造函数,即不同种类的组件,其对应的 VueComponent 构造函数不同,以此来区分组件的种类
  2. Vue在解析模板时 ,会对每个组件标签 都调用一次对应的构造函数,返回的实例 都是互不影响的,以此来区分同种组件不同实例(同种组件在出现在页面不同位置,展示不同内容)

vm与vc {#vm与vc}

VueComponent() 的实例对象,简称vc (也可称之为:组件实例对象)
Vue() 的实例对象,简称vm

对vm和vc的理解:
1、 vm 和 vc 长得差不多(属性和方法都一样的),因为 Vue(options)VueComponent(options) 两个构造函数,在源码中都是调用了其原型上_init(options)

2、 vm 或 vc 的 $children 属性以数组 形式保存着 vm 或 vc 所管理的组件子组件实例对象

3、 组件是可复用 的 Vue 实例(vm),所以它们与 new Vue() 接收相同的配置选项 options ,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

**4、**vc 由 vm 管理,vc 没有 el 配置,只有 vm 能通过 el 配置来指定为谁服务

重要内置关系 {#重要内置关系}

VueComponent.prototype.proto = Vue.prototype

复习原型与原型链JavaScript基础笔记(3)---原型与原型链

$mount、$watch 等属性和方法都在 Vue.prototype 上,也就是 Vue 的原型上

作用: 这个重要的内置关系将组件的原型Vue的原型 通过 proto 相连,使 VueComponent 继承 Vue原型,让组件实例顺着原型链也能使用$mount、$watch 等属性和方法,

目的:组件实例对象 (vc)可以访问到Vue原型上的属性、方法

单文件组件 {#单文件组件}

单文件组件: 一个文件中仅包含一个组件,文件后缀为 .vue

浏览器并不认识.vue文件,需要通过 webpack脚手架 ,将其加工为JS文件

文件名推荐规则: 单个单词大写 ,多个单词双驼峰

.vue文件中代码分为三个标签

  1. <template> => 组件的结构
  2. <script> => 组件交互相关代码,包含组件所用的数据、方法
  3. <style> => 组件的样式

主要的文件: 需放入脚手架中才能运行
1、xxx.vue 各种组件
2、App.vue 汇总所有组件
3、main.js 入口文件,创建Vue实例,注册App组件并应用
4、index.html 页面 一个简单的组件

|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <template> <!-- 组件的结构 --> <div class="student"> <h2>{{ name }}}</h2> <h3>{{ age }}}</h3> </div> </template> <script> // 组件交互相关代码 // 省略Vue.extend,直接暴露组件的配置对象 export default { name: 'Student', //最好与文件名保持一致 data() { return { name: 'chuckle', age: '19' } } } </script> <style> /* 组件的样式 */ .student { background: #ccc; border-radius: 8px; } </style> |

必须有 App.vue 汇总所有组件

|------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <template> <div> <School></School> </div> </template> <script> // 引入Student组件 import School from "./Student.vue" export default { name: "App", components: { School } } </script> <style></style> |

main.js 入口文件,创建Vue实例,注册App组件并应用

|------------------------------|-----------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 | import App from "./App.vue" // 引入App组件 new Vue({ el: '#root', template: '<App></App>', components: { App } }) |

index.html 页面

|------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <!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> <!-- 引入vue文件 --> <script src="../../js/vue.js"></script> <!-- 引入入口文件 --> <script src="./main.js"></script> </body> </html> |

脚手架Vue-cli {#脚手架Vue-cli}

Vue 脚手架是 Vue 官方提供的标准化开发工具(开发平台)

Vue 有多种脚手架,Vue-cli 是其中一种

起步 {#起步}

安装: 该全局模块会暴露一个全局命令vue

|-----------|---------------------------------| | 1 | npm install -g @vue/cli |

创建一个项目

|-----------|--------------------------| | 1 | vue create <项目名> |

选择项目的vue版本,babel用于ES6转ES5,eslint语法检查

|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 | Vue CLI v5.0.8 ? Please pick a preset: Default ([Vue 3] babel, eslint) > Default ([Vue 2] babel, eslint) Manually select features |

等待安装完毕,运行项目

|-----------|-----------------------| | 1 | npm run serve |

项目文件结构 {#项目文件结构}

默认 HelloWord 项目结构:

|---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ├─ public │ ├─ favicon.ico │ └─ index.html │ ├─ src │ ├─ assets │ │ └─ logo.png │ ├─ components │ │ └─ HelloWorld.vue │ ├─ App.vue │ └─ main.js │ ├─ .gitignore ├─ vue.config.js ├─ babel.config.js ├─ jsconfig.json ├─ package-lock.json ├─ package.json |

文件解释:

1、 根目录中的一些配置文件:

  1. babel.config.js babel控制文件,脚手架已写好,无需再动
  2. package.json 定义了当前项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等)
  3. package-lock.json 锁定所有模块的版本号,包括主模块和所有依赖子模块
  4. .gitignore git忽略文件配置
  5. jsconfig.json 指定根文件和JavaScript语言服务提供的功能选项,明确项目的文件范围
  6. vue.config.js 一个可选的脚手架配置文件,进行vue项目本地运行和构建相关配置,若根目录中存在这个文件,它会被 @vue/cli-service 自动加载

2、src文件夹: 有些熟悉的文件,main.js入口文件、app.vue组件等
- assets文件夹: 存放静态资源
- **components:**存放组件,除了App组件 main.js有一些变化

|---------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // 整个项目的入口文件 // 引入Vue import Vue from 'vue' // 引入App组件,是所有组件的父组件 import App from './App.vue' // 关闭Vue的生产环境提示 Vue.config.productionTip = false // 创建Vue实例对象 new Vue({ // 将App组件放入容器中 render: h => h(App), }).$mount('#app') // 绑定容器 |

**3、public文件夹:**页面的根目录,存放了index.html和ico图标

**应该知道:**main.js之所以是入口文件,而且它能找到public中的index.html去绑定容器,是脚手架配置、规定的

render函数 {#render函数}

在 main.js 中,render: h => h(App) 作用是将App组件放入容器中

若使用之前的模板写法,控制台会报错 模板写法

|---------------------------|-----------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 | import App from "./App.vue" // 引入App组件 new Vue({ el: '#root', template: '<App></App>', components: { App } }) |

报错内容: [vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
**意思是:**正在使用Vue的仅运行时版本(runtime模式),其中模板编译器不可用。将模板预编译为render函数,或者使用包含编译器的内部版本。

问题原因:
Vue包含两个部分,核心部分模板解析器 ,核心部分是生命周期与各种属性与函数,模板解析器用于解析模板,当通过cdn引入来使用Vue时,应该将两者都引入,但如果使用脚手架、webpack将.vue文件都翻译为.js文件,且模板都已经解析为html ,模板解析器在生产环境就没有用了

因为Vue中不是所有部分都在生产环境中用到,且模板解析器占Vue体积的三分之一,所以Vue除了完整版,还有许多精简版,带模板解析器的称为 compiler(模板)模式 ,反之称为 runtime(运行时)模式

(1) vue.js 是完整版Vue,包含:核心功能+模板解析器
(2) vue.runtime.xxx.js 是运行版Vue,只包含核心功能,没有模板解析器

通过 import Vue from 'vue' 引入的就是不带模板解析器的精简版,vue模块的package.json的main/model字段默认为runtime模式,指向了"dist/vue.runtime.common.js"。

解决办法一:引入完整版Vue,不推荐

|-----------|-------------------------------------------| | 1 | import Vue from 'vue/dist/vue.js' |

解决办法二 :使用渲染函数 render() 代替模板写法

render 配置项是一个函数,传入 createElement 参数也是一个函数

createElement() 可以创建具体的元素,可以传入一个组件 或是 ('标签名','标签内容')的形式 ,返回创建好的元素

Vue会调用 render() 并接收其返回值,将 createElement() 的返回值(创建好的元素)返回即可

|---------------------|-----------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 | // 完整写法 render(createElement) { return createElement('h1', '你好啊') } // 箭头函数简写 render: h => h(App) |

注意: 在开发环境中有 vue-cli 自带有 vue-template-compiler 插件,能解析 .vue 文件中的 <template></template> 模板,但写在配置对象 template 属性中的模板没有插件能解析,所以要使用 render()

以后一般也只有在创建vm时配置项里会用到render

自定义脚手架配置 {#自定义脚手架配置}

脚手架默认使用main.js作为入口文件等默认配置都在一个文件中,该文件被隐藏了起来

使用命令导出、查看脚手架配置文件的拷贝

|-----------|---------------------------------| | 1 | vue inspect > output.js |

vue-cli配置参考项中查看可配置项

vue.config.js 文件中进行自定义配置

|-------------------|--------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 | // vue.config.js const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ // 配置选项 }) |

ref标签属性 {#ref标签属性}

替代 id 属性给元素或子组件 注册引用信息(打标识)

元素标签组件标签 添加 ref 属性,就能在组件实例对象的 $refs 上获取dom元素子组件实例对象

|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 | <!-- 打标识 --> <h1 v-text="msg" ref="xxx"></h1> <School ref="xxx"></School> <!-- 获取dom元素或子组件vc --> <script> this.$refs.xxx </script> |

|---------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <template> <div> <h1 v-text="msg" ref="title"></h1> <button @click="showTitle">显示/隐藏标题</button> <School></School> </div> </template> <script> import School from "./components/school.vue"; export default { name: "App", components: { School, }, data() { return { msg: "学校信息", }; }, methods: { showTitle() { this.$refs.title.classList.toggle('hide'); }, }, }; </script> <style> .hide { opacity: 0; } </style> |

props配置项 {#props配置项}

子组件的 props 配置项接收父组件通过组件标签传入的数据

**作用:**实现父组件与子组件的通信

通过标签属性给子组件传数据

注意:

  1. 普通属性传的是字符串 ,要传入其它数据类型 的属性,需要 v-bind 绑定属性,传入表达式的值
  2. 传入引用数据类型时,传的是引用,浅拷贝

|-----------|--------------------------------------------------------------| | 1 | <Student name="chuckle" sex="男" :age="18"></Student> |

子组件接收数据,三种写法

|------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // 简单接收,不对数据类型进行限制 props: ['name', 'age', 'sex'] // 接收同时限制数据类型 props: { name: String, age: Number, sex: String } // 更多配置,必须的、默认值等 props: { name: { type: String, required: true // 必须的 }, age: { type: Number, required: true // 必须的 }, sex: { type: String, default: "男" } } |

props 接收到的数据会代理到 vc 身上,但不允许修改 只能读取(直接修改也有效果,但控制台会发出警告),所以也不能使用 v-model 绑定

若需修改,应先将数据拷贝到data中,用一个新属性接收

|-------------------|-----------------------------------------------------| | 1 2 3 4 5 | data() { return { myAge: this.age + 1 }; }, |

mixins混入 {#mixins混入}

多个相似组件中通常会有重复的配置项,可以将这些配置项提取成一个混入对象,给这些组件引入复用(混入)

将相同的配置项提取至 mixin.js mixin.js

|---------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | export const mixin1 = { data(){ return { x: 100, y: 200 } } } export const mixin2 = { data() { return { name: '', } }, methods: { showName(){ console.log(this.name); } }, } |

组件通过 mixins 配置项引入 mixin.js 中的配置

Vue会将这些外部的配置混入 组件的同名配置中(混合合并),配置中重复的属性保留组件中的

mixins: [] 局部混入 局部组件混入

|---------------------|----------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 | // 引入混入对象文件 import {mixin1, mixin2} from '../mixin.js'; export default { // 局部混入 mixins: [mixin1,mixin2], }; |

Vue.mixin() 全局混入 在main.js中全局混入,给所有组件

|---------------|-----------------------------------------------------------------------------------------| | 1 2 3 | import {mixin1, mixin2} from '../mixin.js'; Vue.mixin(mixin1) Vue.mixin(mixin2) |

插件 {#插件}

Vue中插件本质是一个对象,对象中必须有一个 install() 方法

plugins.js 或其它名字的独立js文件中定义插件

|-------------------|----------------------------------------------------------------| | 1 2 3 4 5 | export default { install(){ console.log('这是一个插件'); } } |

main.js 中导入并使用 Vue.use() 应用插件

|-----------------|----------------------------------------------------------------------------| | 1 2 3 4 | // 导入插件 import plugins from "./plugins"; // 使用插件 Vue.use(plugins); |

插件对象的 install() 方法默认第一个参数 接收 Vue构造函数 作为参数,在插件中可以进行各种全局配置以及在原型上添加属性和方法 plugins.js

|------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import {mixin1, mixin2} from './mixin.js'; export default { // 第一个参数接收Vue构造函数作为参数 install(Vue){ // 配置全局过滤器 Vue.filter('interceptStr',(value, num=4)=>{ return value.slice(0,num) }) // 注册全局自定义指令 Vue.directive('inHtml', function(el, binding){ el.innerHTML = binding.value }) // 应用全局混入 Vue.mixin(mixin1) Vue.mixin(mixin2) // 在Vue原型上添加属性和方法 Vue.prototype.hello = function(){ console.log('Hello') } } } |

自定义参数:
Vue.use() 使用插件时也可以传入其它参数,会被 install() 方法接收,第一个参数仍然是 Vue构造函数

|-------------------|-----------------------------------------------------------------------------------------------------| | 1 2 3 4 5 | // 传入三个自定义参数,三个数字 Vue.use(plugins,1,2,3); install(Vue,a,b,c){ console.log(a,b,c);// 1 2 3 } |

scoped样式 {#scoped样式}

多个组件有多个 style 标签,所有组件样式都会汇总到一个 CSS 文件中

当组件中有相同类名时,样式就会冲突,可以给组件的 style 标签加上 scoped 属性解决冲突

**作用:**让样式仅在当前组件中生效,防止样式冲突

原理: 当style标签加上 scoped 属性后,Vue会给该组件所有标签元素都加上一个随机的 data-v 属性,css选择器也会自动选择 data-v

|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 | <div data-v-22321ebb="" class="demo"> <h2 data-v-22321ebb="">学生姓名:chuckle</h2> <h2 data-v-22321ebb="">学生性别:男</h2> <h2 data-v-22321ebb="">学生年龄:19</h2> <hr data-v-22321ebb=""> </div> |

|---------------|-------------------------------------------------------------------| | 1 2 3 | .demo[data-v-22321ebb] { background: rgb(78, 180, 220); } |

注意: 一般在 App.vue 的 style 标签中写全局共用样式,所以 App 不适合加 scoped

更多: style 标签的 lang 属性可以指定 CSS 预处理语言,常用 less ,使用 less 前需要安装 less-loader 用于解析 less

|-------------|---------------------------------------------| | 1 2 | <style lang="less" scoped> </style> |

赞(2)
未经允许不得转载:工具盒子 » Vue笔记[二]-组件化