Vue学习(二)Vue组件化编程

迈不过友情╰ 2022-10-22 13:56 350阅读 0赞

文章目录

  • 一、模块与组件相关概念说明
  • 二、Vue 中使用组件的三大步骤
  • 三、非单文件组件
  • 四、单文件组件
    • 4.1 Vue 单文件组件的组成
    • 4.2 使用 vue-cli 创建模板项目
    • 4.3 项目的打包与发布
  • 五、组件化高级配置项
    • 5.1 一个重要的内置属性
    • 5.2 ref 属性
    • 5.3 mixin
    • 5.4 插件
    • 5.5 scoped 样式
    • 5.6 nextTick
  • 六、组件间通讯
    • 6.1 props 配置项
    • 6.2 组件的自定义事件
    • 6.3 全局事件总线(GlobalEventBus)
    • 6.4 消息订阅与发布(pubsub)
  • 七、Vue 过渡&动画
  • 八、Vue 中的 Ajax
    • 8.1 跨域问题
    • 8.2 vue-resource
    • 8.3 axios
  • 九、组件化编程总结

一、模块与组件相关概念说明

① 模块

理解:向外提供特定功能的js程序,一般就是一个js文件

作用:通常js文件很多很复杂,模块起到了复用js,简化js的编写,提高js运行效率

② 组件

理解: 用来实现局部功能效果的代码集合(html/css/js/image……)

作用: 通常一个界面的功能很复杂,组件起到了复用编码,简化项目编码,提高运行效率

③ 模块化

当应用中的js都以模块来编写的,那这个应用就是一个模块化的应用

④ 组件化

当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用。

二、Vue 中使用组件的三大步骤

① 定义组件

使用Vue.extend(options)创建,其中optionsnew Vue(options)时传入的那个options几乎一样,但也有点区别;

  • 不要写el:最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器
  • data必须写成函数:避免组件被复用时,数据存在引用关系

②注册组件

  • 局部注册:靠new Vue的时候传入components选项
  • 全局注册:靠Vue.component('组件名',组件)

③ 使用组件:使用组件标签<tag></tag>

三、非单文件组件

3.1 基本使用

非单文件组件说明:

  • 模板编写没有提示
  • 没有构建过程,无法将ES6转换成ES5
  • 不支持组件的CSS
  • 真正开发中几乎不用

    1. <!--使用组件标签-->
    2. <school></school>
    3. <student></student>

在这里插入图片描述

3.2 组件化命名规范

① 组件名

一个单词组成:

  • 第一种写法(首字母小写):school
  • 第二种写法(首字母大写):School

多个单词组成:

  • 第一种写法(kebab-case命名):my-school
  • 第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)

备注:

  • 组件名尽可能回避HTML中已有的元素名称,例如:h2H2都不行
  • 可以使用name配置项指定组件在开发者工具中呈现的名字

② 组件标签

第一种写法:<school></school>
第二种写法:<school/>

备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。

③ 声明组件简写方式
const school = Vue.extend(options)可简写为const school = options

3.3 关于VueComponent

  1. school组件本质是一个名为VueComponent的构造函数,是Vue.extend生成的
  2. 我们只需要写<school/><school></school>Vue解析时会帮我们创建school组件的实例对象即Vue帮我们执行new VueComponent(options)
  3. 每次调用Vue.extend,返回的都是一个全新的VueComponent
  4. VueComponent的实例对象简称vc
  5. 关于this指向:组件配置中data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是vc

四、单文件组件

4.1 Vue 单文件组件的组成

① 模板页面

  1. <template>
  2. 页面模板
  3. </template>

② JS 模块对象

  1. <script>
  2. //vue.extends({})的简写
  3. exprot default{
  4. data(){
  5. return{ }
  6. },
  7. methods: { },
  8. computed:{ },
  9. components: { }
  10. }
  11. </script>

③ 样式

  1. <style>
  2. 样式定义
  3. <style/>

4.2 使用 vue-cli 创建模板项目

① 创建vue项目

vue-cli是vue官方提供的脚手架工具

  1. # 安装vue-cli
  2. npm install -g vue-cli
  3. # 构建vue项目
  4. vue init webpack vue-demo
  5. # 安装依赖
  6. npm install
  7. # 运行项目
  8. npm run dev

访问localhost:8080,效果如下:
在这里插入图片描述
② 模板项目结构
在这里插入图片描述
③ template属性的作用
在这里插入图片描述
template参数绑定的组件替换给绑定的el标签值对应的index.html中的元素app

④ render 函数

vue.jsvue.runtime.xxx.js的区别:

  • vue.js是完整版的Vue,包含核心功能+模板解析器
  • vue.runtime.xxx.js是运行版的Vue,只包含核心功能;没有模板解析器

因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用。

render函数接收到的createElement函数去指定具体内容,实现了将App组件放入容器中。

⑤ eslint:用于做项目编码规范检查的工具

基本原理:定义了很多规则,检查项目的代码一旦发现违背了某个规则就输出相应的提示信息有相应的配置,可定制检查。

webstorm关闭编码时候的检查:setting->搜索ESLint->关闭Enable

⑥ vue.config.js配置文件

  • 使用vue inspect > output.js可以查看到Vue脚手架的默认配置
  • 使用vue.config.js可以对脚手架进行个性化定制,详情见地址

4.3 项目的打包与发布

① 打包

  1. # 使用该命令生成dist文件
  2. npm run build

② 发布

方式一:使用静态服务器工具包

  1. # 安装静态服务器
  2. npm install -g serve
  3. # 运行项目
  4. serve dist
  5. # 访问所给连接即可

方式二:使用动态web服务器(tomcat),将生成的dist文件扔到tomcatwebapp下即可。

五、组件化高级配置项

5.1 一个重要的内置属性

一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype

为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性、方法。

5.2 ref 属性

  1. 被用来给元素或子组件注册引用信息(id的替代者)
  2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc
  3. 使用方式:

    1. 打标识:<h1 ref="xxx">.....</h1><School ref="xxx"></School>
    2. 获取:this.$refs.xxx

参考代码如下:

  1. <template>
  2. <div id="app">
  3. <h1 ref="msg">{ { msg}}</h1>
  4. <School ref="school"/>
  5. <button @click="showDom">showDom</button>
  6. </div>
  7. </template>
  8. <script>
  9. import School from './components/School.vue'
  10. export default {
  11. name: 'App',
  12. components: {
  13. School
  14. },
  15. data(){
  16. return{
  17. msg:'----Vue学习----'
  18. }
  19. },
  20. methods:{
  21. showDom(){
  22. console.log(this.$refs.school)
  23. console.log(this.$refs.msg)
  24. }
  25. }
  26. }
  27. </script>
  28. <style>
  29. </style>

在这里插入图片描述

5.3 mixin

mixin功能:可以把多个组件共用的配置提取成一个混入对象

使用方式:

  • 定义混入
  • 使用混入

    • 全局混入:Vue.mixin(xxx)
    • 局部混入:mixins:['xxx']

示例代码:

定义混入mixin.js

  1. export const mixin1 = {
  2. methods: {
  3. showName() {
  4. alert(this.name)
  5. }
  6. },
  7. mounted() {
  8. console.log('你好啊!')
  9. }
  10. }

局部混入:

  1. <script>
  2. import { mixin1} from '../mixin.js'
  3. export default {
  4. name: 'School',
  5. data () {
  6. return {
  7. name:'Peking',
  8. location: 'Beijing'
  9. }
  10. },
  11. mixins:[mixin1]
  12. }
  13. </script>

全局混入main.js

  1. import Vue from 'vue'
  2. import App from './App'
  3. import { mixin1} from './mixin.js'
  4. Vue.config.productionTip = false
  5. Vue.mixin(mixin1)
  6. new Vue({
  7. el: '#app',
  8. render: h => h(App)
  9. })

5.4 插件

插件功能:用于增强Vue,插件的功能范围没有严格的限制,一般有下面几种:

  • 添加全局方法或者属性,如: vue-custom-element
  • 添加全局资源(指令/过滤器/过渡等),如 vue-touch
  • 通过全局混入来添加一些组件选项,如 vue-router
  • 添加Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
  • 一个库,提供自己的API,同时提供上面提到的一个或多个功能,如vue-router

本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

自定义插件:

  1. 对象.install = function (Vue, options) {
  2. // 1. 添加全局过滤器
  3. Vue.filter(....)
  4. // 2. 添加全局指令
  5. Vue.directive(....)
  6. // 3. 配置全局混入(合)
  7. Vue.mixin(....)
  8. // 4. 添加实例方法
  9. Vue.prototype.$myMethod = function () { ...}
  10. Vue.prototype.$myProperty = xxxx
  11. }

使用插件Vue.use()

示例代码:

定义插件方式一:

  1. //插件定义方式一
  2. // export default {
  3. // install(Vue, x, y, z) {
  4. // console.log(x, y, z)
  5. // //定义混入
  6. // Vue.mixin({
  7. // methods: {
  8. // showName() {
  9. // alert(this.name)
  10. // }
  11. // }
  12. // })
  13. // }
  14. // }
  15. //插件定义方式二
  16. const MyPlugin = { }
  17. MyPlugin.install = function(Vue, a,b,c) {
  18. console.log(a,b,c)
  19. //定义混入
  20. Vue.mixin({
  21. methods: {
  22. showName() {
  23. alert(this.name)
  24. }
  25. }
  26. })
  27. }
  28. export default MyPlugin

使用插件main.js

  1. import Vue from 'vue'
  2. import App from './App'
  3. // import plugin from './plugin.js'
  4. import MyPlugin from './plugin.js'
  5. Vue.config.productionTip = false
  6. Vue.use(MyPlugin, 1, 2, 3)
  7. new Vue({
  8. el: '#app',
  9. render: h => h(App)
  10. })

测试效果:使用插件后Vue获得了混入属性
在这里插入图片描述

5.5 scoped 样式

作用:让样式在局部生效,防止冲突。

写法:<style scoped>

5.6 nextTick

语法:this.$nextTick(回调函数)

作用:在下一次DOM更新结束后执行其指定的回调。

什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。

六、组件间通讯

6.1 props 配置项

props功能是让组件接收外部传过来的数据,传递数据的方式:<Demo name="xxx"/>,当传递数据类型不为String类型的时候,应使用<Demo :age="xxx"/>,接收方式有如下3种方式:

  1. 第一种方式(只接收):props:['name']
  2. 第二种方式(限制类型):props:{name:String}
  3. 第三种方式(限制类型、限制必要性、指定默认值):

③ props 属性

  • 父组件 ==> 子组件 通信
  • 子组件 ==> 父组件 通信(要求父先给子一个函数)

    备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
    因此在使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
    >

组件Student代码:

  1. <template>
  2. <div>
  3. <h2>姓名:{ { name }}</h2>
  4. <h2>年龄:{ { age+1 }}</h2>
  5. <h2>家乡:{ { home }}</h2>
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. name: 'Student',
  11. data() {
  12. return {
  13. name: 'Joker',
  14. age: this.parent_age,
  15. home: 'Beijing'
  16. }
  17. },
  18. //1、简单的声明接收
  19. // props:['name','age','home'],
  20. //2、对数据类型进行限制
  21. // props: {
  22. // name: String,
  23. // age: Number,
  24. // home: String
  25. // },
  26. //3、接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
  27. props: {
  28. name: {
  29. type: String, //name的类型是字符串
  30. required: true, //name是必要的
  31. },
  32. parent_age: {
  33. type: Number,
  34. default: 99 //默认值
  35. },
  36. home: {
  37. type: String,
  38. required: true
  39. }
  40. }
  41. }
  42. </script>
  43. <style>
  44. </style>

App.vue代码:

  1. <template>
  2. <div id="app">
  3. <h1 ref="msg">{ { msg}}</h1>
  4. <Student name="Frank" :parent_age="14" home="Shanghai"/>
  5. </div>
  6. </template>
  7. <script>
  8. import Student from './components/Student.vue'
  9. export default {
  10. name: 'App',
  11. components: {
  12. Student
  13. },
  14. data(){
  15. return{
  16. msg:'----Vue学习----'
  17. }
  18. }
  19. }
  20. </script>
  21. <style>
  22. </style>

6.2 组件的自定义事件

前面我们讲过子组件向父组件通信可以使用props属性,但需要父组件传递给子组件回调函数。我们可以采用组件的自定义事件同样达到子组件传递父组件通信。

使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)

① 绑定自定义事件

  1. 在父组件中<School @schoolEvent="getSchoolName"/><School v-on:schoolEvent="getSchoolName"/>
  2. 第二种方式,在父组件中定义事件:

    1. <Student ref="student"/>
    2. //在mounted函数中绑定
    3. mounted(){
    4. this.$refs.student.$on('studentEvent', this.getStudentName)
    5. }
  3. 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法,例:this.$refs.student.$once('atguigu',this.getStudentName)

② 触发自定义事件

this.$emit('studentEvent', this.name, 3, 4, 5)

③ 解绑自定义事件

  • 解绑具体事件:this.$off('schoolEvent')
  • 解绑多个事件:this.$off(['schoolEvent', 'testEvent'])
  • 解绑所有事件:this.$off()

④ 组件上也可以绑定原生DOM事件,需要使用native修饰符

⑤ 注意事项

注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!

6.3 全局事件总线(GlobalEventBus)

一种组件间通信的方式,适用于任意组件间通信。

① 安装全局事件总线

  1. new Vue({
  2. ......
  3. beforeCreate() {
  4. //安装全局事件总线,$bus就是当前应用的vm
  5. Vue.prototype.$bus = this
  6. },
  7. ......
  8. })

② 使用事件总线

  1. 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。

    1. methods(){
    2. demo(data){ ......}
    3. }
    4. ......
    5. mounted() {
    6. this.$bus.$on('xxxx',this.demo)
    7. }
  2. 提供数据:this.$bus.$emit('xxxx',数据)
  3. 解绑事件:最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件

6.4 消息订阅与发布(pubsub)

  1. 一种组件间通信的方式,适用于任意组件间通信。
  2. 使用步骤:

    1. 安装pubsubnpm i pubsub-js
    2. 引入:import pubsub from 'pubsub-js'
    3. 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

      1. methods(){
      2. demo(data){ ......}
      3. }
      4. ......
      5. mounted() {
      6. this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
      7. }
    4. 提供数据:pubsub.publish('xxx',数据)
    5. 最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。

七、Vue 过渡&动画

vue动画:操作csstrasitionanimationvue会给目标元素添加/移除特定的class

过渡的相关类名:
- xxx-enter-active: 指定显示的transition
- xxx-leave-active: 指定隐藏的transition
- xxx-enter/xxx-leave-to: 指定隐藏时的样式
在这里插入图片描述

基本过渡动画的编码:

1)准备好样式

  • 元素进入的样式
    - v-enter:进入的起点
    - v-enter-active:进入过程中
    - v-enter-to:进入的终点
  • 元素离开的样式
    - v-leave:离开的起点
    - v-leave-active:离开过程中
    - v-leave-to:离开的终点

2)使用<transition>包裹要过度的元素,并配置name属性

3)若有多个元素需要过度,则需要使用<transition-group>,且每个元素都要指定key

  1. <style type="text/css">
  2. .fade-enter-active, .fade-leave-active {
  3. transition: opacity 1s;
  4. }
  5. .fade-enter, .fade-leave-to {
  6. opacity: 0;
  7. }
  8. </style>
  9. <div id="app">
  10. <button @click="show=!show">
  11. 过渡&动画
  12. </button>
  13. <transition name="fade">
  14. <p v-if="show">Hello</p>
  15. </transition>
  16. </div>
  17. <script src="node_modules/vue/dist/vue.js"></script>
  18. <script type="text/javascript">
  19. new Vue({
  20. el: '#app',
  21. data: {
  22. show: true
  23. }
  24. })
  25. </script>

效果:
在这里插入图片描述

八、Vue 中的 Ajax

8.1 跨域问题

① 脚手架配置代理解决方法一

vue.config.js中添加如下配置:

  1. devServer:{
  2. proxy:"http://localhost:5000"
  3. }

说明:

  1. 优点:配置简单,请求资源时直接发给前端(8080)即可。
  2. 缺点:不能配置多个代理,不能灵活的控制请求是否走代理。
  3. 工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器 (优先匹配前端资源)

② 脚手架配置代理方法二

编写vue.config.js配置具体代理规则:

  1. module.exports = {
  2. devServer: {
  3. proxy: {
  4. '/api1': { // 匹配所有以 '/api1'开头的请求路径
  5. target: 'http://localhost:5000',// 代理目标的基础路径
  6. changeOrigin: true,
  7. pathRewrite: { '^/api1': ''}
  8. },
  9. '/api2': { // 匹配所有以 '/api2'开头的请求路径
  10. target: 'http://localhost:5001',// 代理目标的基础路径
  11. changeOrigin: true,
  12. pathRewrite: { '^/api2': ''}
  13. }
  14. }
  15. }
  16. }
  17. /* changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000 changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080 changeOrigin默认值为true */

说明:

  1. 优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
  2. 缺点:配置略微繁琐,请求资源时必须加前缀。

8.2 vue-resource

vue插件,非官方库,vue1.x使用广泛。

  1. 安装vue-resourcenpm i vue-resource
  2. main.js中引入VueResource模块

    1. import VueResource from 'vue-resource'
    2. Vue.use(VueResource)
  3. 通过vue组件对象发送ajax请求

    1. <script>
    2. new Vue({
    3. methods: {
    4. testVueResource() {
    5. this.$http.get('/someUrl').then((response) => {
    6. console.log(response.data)
    7. }, (error) => {
    8. console.log(error.statusText)
    9. })
    10. }
    11. }
    12. })
    13. </script>

8.3 axios

通用的ajax请求库,官方推荐,vue2.x使用广泛。实例参考axios 学习

九、组件化编程总结

① 组件的拆分

通常我们是对已有的传统前端项目进行改造成Vue项目,比如下方这个静态页面:

拿到这个静态资源后我们需要对静态资源进行组件上的拆分,如下图,我们将静态资源分成了三大部分:UserHeaderUserListUserFooter,其中UserList又是由多个UserItem组成。
在这里插入图片描述
首先我们先创建各个组件,然后将静态资源htmlcss放入到App,然后将对应的htmlcss样式移入到对应的组件中。

通过分析,我们Todos数据在各个组件均会用到,那么我们边将数据定义在App组件中,我们通过props属性将父级数据传递给子级数据。

② 组件化编码流程

  1. 拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突
  2. 实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用

    1. 一个组件在用:放在组件自身即可
    2. 一些组件在用:放在他们共同的父组件上(状态提升)
  3. 实现交互:从绑定事件开始

④ webStorage

  1. 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
  2. 浏览器端通过Window.sessionStorageWindow.localStorage属性来实现本地存储机制。
  3. 相关 API
    1)xxxxxStorage.setItem(‘key’, ‘value’):该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
    2)xxxxxStorage.getItem(‘person’):该方法接受一个键名作为参数,返回键名对应的值
    3)xxxxxStorage.removeItem(‘key’):该方法接受一个键名作为参数,并把该键名从存储中删除
    4)xxxxxStorage.clear():该方法会清空存储中的所有数据
  4. 备注:

    1)SessionStorage存储的内容会随着浏览器窗口关闭而消失
    2)LocalStorage存储的内容,需要手动清除才会消失
    3)xxxxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么getItem的返回值是null
    4)JSON.parse(null)的结果依然是null

发表评论

表情:
评论列表 (有 0 条评论,350人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Vue 开发

    Vue 组件化开发 什么叫做组件化 实例 什么叫做组件化 所谓组件化,就是把页面拆分成多个组件然后可重复利用,每个组件依赖的 CSS、JS、模板、图片

    相关 Vue应用构建

    组件化应用构建   组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽

    相关 vue 应用构建

    组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。 ![70][] 在 Vue 里,一个组件本质上是一个拥

    相关 Vue.js 开发

    三、组件化开发 1.1 组件化的实现和使用步骤 组件注册步骤解析 1.2 全局组件和局部组件 1.3 父组件和子组件 1.4 注册组件