3、Vue脚手架

文章目录

1、创建Vue脚手架

2、render函数

3、ref属性/props配置/mixin混入

4、插件

5、scoped样式

6、本地存储

7、事件

8、消息订阅与发布

9、Vue封装的过度与动画

10、配置代理

11、vue-resource

12、插槽

一、创建Vue脚手架

1、说明

  • Vue脚手架是Vue官方提供的标准化开发工具(开发平台)
  • 最新的版本是4.x
  • 文档:https://cli.vuejs.org/zh/

2、具体步骤

第一步(仅第一步执行):全局安装@vue/cli

npm install -g @vue/cli

第二步:切换到你要创建项目的目录,然后使用命令创建项目

vue create testProject

第三步:启动项目

npm run serve

备注:

  • 如出现下载缓慢,请配置npm淘宝镜像:npm config set registry https://registry.npm.taobao.org
  • Vue脚手架隐藏了所有webpack相关的配置,若想查看具体的webpack配置,请执行:vue inspect > output.js

3、脚手架结构

├── node_modules

├── public

│ ├── favicon.ico: 页签图标

│ └── index.html: 主页面

├── src

│ ├── assets: 存放静态资源

│ │ └── logo.png

│ │── component: 存放组件

│ │ └── HelloWorld.vue

│ │── App.vue: 汇总所有组件

│ │── main.js: 入口文件

├── .gitignore: git版本管制忽略的配置

├── babel.config.js: babel的配置文件

├── package.json: 应用包配置文件

├── README.md: 应用描述文件

├── package-lock.json:包版本控制文件

4、修改默认配置

  • Vue脚手架隐藏了所有webpack相关的配置,若想查看具体的webpack配置,请执行:vue inspect > output.js,打开的output.js的文件只是抛出展示相关的webpack配置,修改是无效的
  • 文件夹的public、文件夹src、文件public/index.html、文件public/favicon.ico、文件src/main.js、文件package.json是不允许更改名称的
  • 要改默认配置,需借助vue.config.js文件,同package.json是同级的
module.exports = {
  pages: {
    index: {
      // page 的入口
      entry: 'src/index/main.js',
      // 模板来源
      template: 'public/index.html',
      // 在 dist/index.html 的输出
      filename: 'index.html',
      // 当使用 title 选项时,
      // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
      title: 'Index Page',
      // 在这个页面中包含的块,默认情况下会包含
      // 提取出来的通用 chunk 和 vendor chunk。
      chunks: ['chunk-vendors', 'chunk-common', 'index']
    },
    // 当使用只有入口的字符串格式时,
    // 模板会被推导为 `public/subpage.html`
    // 并且如果找不到的话,就回退到 `public/index.html`。
    // 输出文件名会被推导为 `subpage.html`。
    subpage: 'src/subpage/main.js',
    lintOnSave: false, // 关闭语法检查
  }
}

二、render函数

  • vue.js与vue.runtime.xxx.js的区别:
    1. vue.js是完整版的Vue,包含:核心功能+模板解析器
    2. vue.runtime.xxx.js是运行版的vue,只包含:核心功能,没有模板解析器
  • vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数区指定具体的内容
// 引用到的vue是vue.runtime.xxx.js,只包含:核心功能,没有模板解析器
import Vue from 'vue'
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

new Vue({
    el: '#root',
    // 不能使用template,没有模板解析器
    // 需借助render函数,返回要渲染的元素
    // render(createElement) {
    //     // createElement函数是创建虚拟dom节点的,接收两个参数,第一个是标签名,第二个是内容
    //     // return createElement('h1', '你好啊!')
    //     return createElement(App)
    // }
    render: h => h(App)
})

通俗易懂的距离讲解:

装修–铺瓷砖

  • 第一种:买瓷砖(Vue核心) + 买工人(模板解析器) ====> 铺好的瓷砖 + 工人

    装修完后,获得了铺好的瓷砖,还得一直养着工人

  • 第二种:买瓷砖(Vue核心) + 雇工人(模板解析器) ====> 铺好的瓷砖

细节问题:

组件还是有template,借助vue-template-compiler这个依赖库来解析

三、ref属性/props配置/mixin混入

1、ref属性

<template>
  <div>
      <h1 v-text="msg" ref="title"></h1>
      <button @click="showDom" ref='btn'>点我输出上方dom元素</button>
      <School ref="sch"></School>
  </div>
</template>

<script>
    // 引入School组件
    import School from './components/School'
    export default {
        name: 'App',
        data() {
            return {
                msg: 'hello'
            }
        },
        components: { School },
        methods: {
            showDom() {
                console.log(this.$refs)
                console.log(this.$refs.title, this.$refs.btn) // 真实dom元素
                console.log(this.$refs.sch) // 获取到School组件实例对象(vc)
            }
        }
    }
</script>
  • 被用来给元素或子组件注册引用信息(id的替代者)
  • 应用在html标签上获取的是真实dom元素,应用在组件标签上是组件实例对象(vc)
  • 使用方式:
    1. 打标识:<h1 ref="xxx"></h1><School ref="xxx"></School>
    2. 获取:this.$refs.xxx

2、props配置

<template>
    <div>
        <h1>{{msg}}</h1>
        <h2>姓名:{{name}}</h2>
        <h2>年龄:{{age}}</h2>
        <h2>性别:{{sex}}</h2>
    </div>
</template>

<script>
    export default {
        name: 'School',
        // 简单声明接收
        // props: ['name', 'age', 'sex'],
        // 接收的同时对数据进行类型限制
        // props: {
        //     name: String,
        //     age: Number,
        //     sex: String
        // },
        // 接收的同时对数据进行类型限制 + 默认值的指定 + 必要性的限制
        props: {
            name: {
                type: String,
                required: true // 是否必要
            },
            age: {
                type: Number,
                default: 99 // 默认值
            },
            sex: {
                type: String,
                required: true
            }
        },
        data() {
            return {
                msg: 'hello'
            }
        }
    }
</script>
  • 简单声明接收: props: ['name', 'age', 'sex']

  • 接收的同时对数据进行类型限制: props: { name: String, age: Number, sex: String }

  • 接收的同时对数据进行类型限制 + 默认值的指定 + 必要性的限制:

    props: { name: { type: String, required: true // 是否必要 }, age: { type: Number, default: 99 // 默认值 }, sex: { type: String, required: true } }

  • 备注:

    props是只读的,Vue底层会监测你对props的修改。如果进行了修改,就会发出警告。若业务需求确实要修改,那么请复制props的内容到data中一份,然后去修改data中的数据

3、mixin混入(混合)

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

  • 使用方式:

    1. 第一步定义混合:

      { data() {...}, methods: {...}, ... }

    2. 使用混入,例如:

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

四、插件

plugins.js插件,代码如下所示:

export default {
    install(Vue) {
        // 全局过滤器
        Vue.filter('mySlice', function(value){
            return value.slice(0, 4)
        })
        // 自定义全局指令
        Vue.directive('fbind', {
            // 指令与元素成功绑定时(一上来)
            bind(element, binding) {
                element.value = binding.value
            },
            // 指令所在的元素被插入页面时
            inserted(element, binding) {
                element.focus()
            },
            // 指令所在的模板被重新解析时
            update(element, binding) {
                element.value = binding.value
            }
        })
        // 定义混入
        Vue.mixin({
            data () {
                return {
                    x: 100
                }
            }
        })
        // 给Vue的原型加上方法(vm和vc都能用)
        Vue.prototype.hello = () => alert('你好啊')
        console.log('这是一个插件', Vue)
    }
}

main.js使用插件

import Vue from 'vue'
import App from './App.vue'
// 引入插件
import plugins from './plugins.js'
//关闭Vue的生产提示
Vue.config.productionTip = false

// 应用(使用)插件
Vue.use(plugins)

// 创建vm
new Vue({
    el: '#app',
    render: h => h(App)
})
  • 功能:用于增强vue
  • 本质:包含install方法的一个对象,install的第一个参数时Vue,第二个以后的参数时插件使用者传递的数据
  • 定义插件:对象.install = function (Vue, options) { ... }
  • 使用插件: Vue.use()

五、scoped样式

  • 作用:让样式在局部生效,阻止冲突
  • 写法: <style scoped></style>

六、本地存储

1、localStorage(本地缓存)

  • 添加缓存:localStorage.setItem(key, value),其中key,value都是string类型,非string类型,会去调用toString()方法
  • 获取缓存:localStorage.getItem(key, value)
  • 清除缓存:localStorage.removeItem(key, value)
  • 清除全部缓存:localStorage.clear()

2、sessionStorage(会话缓存)

  • 添加缓存:sessionStorage.setItem(key, value),其中key,value都是string类型,非string类型,会去调用toString()方法
  • 获取缓存:sessionStorage.getItem(key, value)
  • 清除缓存:sessionStorage.removeItem(key, value)
  • 清除全部缓存:sessionStorage.clear()

3、区别

localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除。

sessionStorage 数据保存在当前会话中,该数据对象临时保存同一窗口 (或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据

4、总结

  • 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)

  • 浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制

  • 相关API:

    1. xxxxxStorage.setItem('key', 'value');

      该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值

    2. xxxxxStorage.getItem('person');

      该方法接受一个键名作为参数,返回键名对应的值

    3. xxxxxStorage.removeItem('key');

      该方法接受一个键名作为参数,并把该键名从存储中删除

    4. xxxxxStorage.clear();

      该方法会清空存储中的所有数据

  • 备注:

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

七、事件

1、组件的自定义事件

// 父组件
// 第一种写法,使用@或v-on
// <School @test="test" @demo="demo"/>
// 第二种写法,使用ref
// <School ref="school" @click.native="show"/> 
// ===> this.$refs.school.$on('test', 需触发的函数) 
// 需触发的函数为function(){}时,this指向所触发的子组件
// 需触发的函数为箭头函数或this.函数名时,this指向父组件
// ===> 想触发原生DOM事件,需加修饰符native,不然会被认为是自定义事件

// 触发School组件实例身上的test事件
this.$emit('test', this, 1, 2) 
this.$emit('demo') 

// 解绑自定义事件
this.$off('test')
// 解绑多个自定义事件
this.$off(['test', 'demo'])
// 解绑所有自定义事件
this.$off()

// 销毁当前Student组件的实例
this.$destroy() // 销毁后所有Student实例的自定义事件全都不奏效
  • 一种组件间通信的方式,适用于:子组件 ===> 父组件

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

  • 绑定自定义事件:

    1. 第一种方式,在父组件中:<Demo @atguigu="test"/><Demo v-on:atguigu="test"/>

    2. 第二种方式,在父组件中:

      <Demo ref="demo"/>
      ......
      mounted(){
         this.$refs.xxx.$on('test',this.test)
      }
      
  • 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法

  • 触发自定义事件:this.$emit('test',数据)

  • 解绑自定义事件:this.$off('tese')

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

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

2、全局事件线

任意组件间通信

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

  • 安装全局事件总线:

    new Vue({
       ......
       beforeCreate() {
          Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
       },
        ......
    }) 
    
  • 使用事件总线:

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

      methods(){
        demo(data){......}
      }
      ......
      mounted() {
        this.$bus.$on('xxxx',this.demo)
      }
      
    2. 提供数据:this.$bus.$emit('xxxx',数据)

    3. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件

八、消息订阅与发布

1、消息订阅与发布

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

  • 引入:import pubsub from 'pubsub-js'

  • 接收数据:A组件想接收数据,则在A组件订阅消息,订阅的回调留在A组件

    <script>
    export default {
        data() {
            return {}
        },
        methods: {
            demo(msgName, data) {......}
        },
        mounted() {
            this.pub = pubsub.subscribe('xxx', this.demo) // 订阅消息
        }
    }
    </script>
    
  • 提供数据:pubsub.publish('demo', 数据)

  • 最好在beforeDestroy钩子中,用pubsub.unsubscribe(pub)去取消订阅

2、_nextTick

  • 语法:this.$nextTick(回调函数)
  • 作用:在下一次 DOM 更新结束后执行其指定的回调
  • 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行

九、Vue封装的过度与动画

<template>
	<div>
		<button @click="isShow = !isShow">显示/隐藏</button>
        <!-- 单个元素过度 -->
        <!--
		<transition name="hello" appear>
			<h1 v-show="isShow">你好啊!</h1>
		</transition>
        -->
        
        <!-- 多个元素过度 -->
        <!--
        <transition-group name="hello" appear>
			<h1 v-show="!isShow" key="1">你好啊!</h1>
			<h1 v-show="isShow" key="2">尚硅谷!</h1>
		</transition-group>
        -->
        
        <!-- 借助animate.css库 -->
        <transition-group 
            appear
			name="animate__animated animate__bounce" 
			enter-active-class="animate__swing"
			leave-active-class="animate__backOutUp"
        >
			<h1 v-show="!isShow" key="1">你好啊!</h1>
			<h1 v-show="isShow" key="2">尚硅谷!</h1>
		</transition-group>
	</div>
</template>

<script>
    import 'animate.css'
	export default {
		name:'Test',
		data() {
			return {
				isShow:true
			}
		},
	}
</script>

<style scoped>
    h1 {
        background-color: orange;
        /* transition: 0.5s linear; */
    }
    /* 方式一 */
    /* 进入的起点、离开的终点 */
    .hello-enter,.hello-enter-to{
        transform: translateX(-100%);
    }
    /* 进入的终点、离开的起点 */
    .hello-enter-to,.hello-enter{
        transform: translateX(0px);
    }
    /* 进入的过程、离开的过程 */
    .hello-enter-active,.hello-leave-active{
		transition: 0.5s linear;
	}
    
    
    /* 方式二 */
    .hello-enter-active{
        animation: test 0.5s linear;
    }
    .hello-leave-active{
        animation: test 0.5s linear;
    }
    
    @keyframes test {
        from {
            transform: translateX(-100%)
        }
        to {
            transform: translateX(0px)
        }
    }
</style>
  • 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。

  • 写法:

    1. 准备好样式:
      • 元素进入的样式:
        1. v-enter:进入的起点
        2. v-enter-active:进入过程中
        3. v-enter-to:进入的终点
      • 元素离开的样式:
        1. v-leave:离开的起点
        2. v-leave-active:离开过程中
        3. v-leave-to:离开的终点
  • 使用<transition>包裹要过度的元素,并配置name属性:

    <transition name="hello">
    	<h1 v-show="isShow">你好啊!</h1>
    </transition>
    
  • 备注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值。

十、配置代理

1、方法一

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

devServer:{
  proxy:"http://localhost:5000"
}

说明:

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

2、方法二

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

module.exports = {
   devServer: {
      proxy: {
      '/api1': {// 匹配所有以 '/api1'开头的请求路径
        target: 'http://localhost:5000',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api1': ''}
      },
      '/api2': {// 匹配所有以 '/api2'开头的请求路径
        target: 'http://localhost:5001',// 代理目标的基础路径
        changeOrigin: true,
        pathRewrite: {'^/api2': ''}
      }
    }
  }
}
/*
   changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
   changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
   changeOrigin默认值为true
*/

说明:

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

十一、vue-resource

请求方法:xhr、jQuery、axios、fetch、vue-resource

vue-resource刚开始是vue团队维护,后面交给其他团队,1.0用得比较多,vue的插件,需了解下

1、安装

npm i vue-resouorce

2、引用插件

import vueResource from 'vue-resource'

3、使用插件

Vue.use(vueResource)

Vue实例vm和组件实例vc,都会多出$http对象,同axios的使用是一样的

十二、插槽

插槽就是子组件提供给父组件的一个占位符,父组件可以在这个占位符填充任何模板代码,如HTML、组件等

插槽显不显示、怎么显示由父组件决定

插槽在哪里显示由子组件决定

1、默认插槽

没有名字的插槽,子组件未定义名字的插槽,父组件把未定义的插槽内容放到默认插槽

子组件child

<template>
    <div>
        <h3>默认插槽</h3>
        <slot></slot>
    </div>
</template>

父组件

<template>
	<div>
        <child>填充默认的插槽内容</child>
        <!-- vue2.6的新写法,必须搭配template标签使用,可简写为# -->
		<child>
            <template v-slot:default>
                <h4>默认插槽-新写法</h4>
                <div>填充默认的插槽内容</div>
			</template>
    	</child>
		<child>
            <template #default>
				<h4>默认插槽-新写法</h4>
                <div>填充默认的插槽内容</div>
			</template>
    	</child>
    </div>
</template>

2、具名插槽

给插槽取个名字,一个子组件可以放多个插槽,而且放在不同的地方;而父组件可以根据插槽的名字,把内容填充到对应的插槽

子组件child

<template>
    <div>
        <slot name='header'></slot>
        <h3>具名插槽</h3>
        <slot name='footer'></slot>
    </div>
</template>

父组件

<template>
	<div>
        <child>
            <div slot="header">插槽头部内容</div>
			<div slot="footer">插槽底部内容</div>
    	</child>
        <child>
            <template slot="header">
                <div>插槽头部内容</div>
			</template>
			<template slot="footer">
                <div>插槽底部内容</div>
			</template>
    	</child>
		<!-- vue2.6的新写法,必须搭配template标签使用,可简写为# -->
		<child>
            <template v-slot:header>
				<h4>具名插槽-新写法</h4>
                <div>插槽头部内容</div>
			</template>
			<template #footer>
				<h4>具名插槽-新写法</h4>
                <div>插槽底部内容</div>
			</template>
    	</child>
    </div>
</template>

3、作用域插槽

其实就是带数据的插槽,子组件提供给父组件的参数,该参数仅限于插槽使用

子组件child

<template>
    <div>
        <slot name='header' :dd='test' msg='hello'></slot>
        <h3>作用域插槽</h3>
        <slot :dd='test' msg='hello'></slot>
    </div>
</template>

<script>
    export default {
        name: 'App',
        data() {
            return {
                test: {
                    name: 'cyr',
                    age: 18
                }
            }
        }
    }
</script>

父组件

父组件

<template>
	<div>
        <child>
            <template scope="{dd}">
                <h3>默认插槽</h3>
                <div>姓名:{{dd.name}}</div>
                <div>年龄:{{dd.age}}</div>
			</template>
    	</child>
		<child>
            <template slot-scope="{dd}">
				<h3>默认插槽</h3>
                <div>姓名:{{dd.name}}</div>
                <div>年龄:{{dd.age}}</div>
			</template>
    	</child>
		<!-- vue2.6的新写法 -->
		<child>
            <template v-slot:default="{dd}">
                <h4>默认插槽-新写法</h4>
                <div>姓名:{{dd.name}}</div>
                <div>年龄:{{dd.age}}</div>
			</template>
    	</child>
		<child>
            <template #default="{dd}">
				<h4>默认插槽-新写法</h4>
                <div>姓名:{{dd.name}}</div>
                <div>年龄:{{dd.age}}</div>
			</template>
    	</child>
		<child>
            <template v-slot:header="{dd}">
				<h4>具名插槽-底部-新写法</h4>
                <div>姓名:{{dd.name}}</div>
                <div>年龄:{{dd.age}}</div>
			</template>
    	</child>
		<child>
            <template #header="{dd}">
                <h4>具名插槽-底部-新写法</h4>
                <div>姓名:{{dd.name}}</div>
                <div>年龄:{{dd.age}}</div>
			</template>
    	</child>
    </div>
</template>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值