「尚硅谷 张天禹」Vue2深入知识

创建Vue脚手架

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

npm install -g @vue/cli

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

vue create xxxx

第三步:启动项目

npm run serve

如果下载缓慢请使用npm淘宝镜像

npm config set registry https://registry.npm.taobao.org

Vue脚手架隐藏了所有webpack相关的配置,若想查看具体配置

vue inspect > output.js

脚手架文件结构

├── 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:包版本控制文件

关于不同版本的Vue

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

vue.js是完整版的Vue,包含:核心功能 + 模板解析器。

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

因为vue.runtime.xxx.js没有模板解析器,所以不能使用template这个配置项,需要使用render函数接收到的createElement函数去指定具体内容。

vue.config.js配置文件

使用vue inspect > output.js可以查看到Vue脚手架的默认配置。

使用vue.config.js可以对脚手架进行个性化定制,详情见:Vue CLI

ref 属性

被用来给元素或子组件注册引用信息(id的替代者)

应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)

使用方式:

① 打标识:<h1 ref="xxx">.....</h1><School ref="xxx"></School>

② 获取:this.$refs.xxx

props配置项

功能:让组件接收外部传过来的数据

传递数据:<Demo name="xxx"/>

接收数据:

第一种方式(只接收):props:['name']

第二种方式(限制类型):props:{name:String}

第三种方式(限制类型、限制必要性、指定默认值):

props:{
    name:{
    type:String, //类型
    required:true, //必要性
    default:'老王' //默认值
    }
}

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

mixin(混入)

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

使用方式:

第一步定义混合:

// 新建js文件,定义方法数据等,需要暴露
export default {
  data(){....},
  methods:{...}
  ...
}

第二步使用混入:

全局混入:

import mixina from './mixin'

Vue.mixin(mixina);

new Vue({
  render: h => h(App),
}).$mount('#app')

局部混入:mixins:['xxx']

插件

功能:用于增强Vue

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

定义插件:

对象.install = function (Vue, options) {
  // 1. 添加全局过滤器
  Vue.filter(....)

  // 2. 添加全局指令
  Vue.directive(....)

  // 3. 配置全局混入(合)
  Vue.mixin(....)

  // 4. 添加实例方法
  Vue.prototype.$myMethod = function () {...}
  Vue.prototype.$myProperty = xxxx
}

使用插件:Vue.use()

scoped样式

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

写法:<style scoped>

TodoList案例

组件化编码流程:

(1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。

(2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:

1).一个组件在用:放在组件自身即可。

2). 一些组件在用:放在他们共同的父组件上(状态提升)。

(3).实现交互:从绑定事件开始。

props适用于:

(1).父组件 ==> 子组件 通信

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

使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!

props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。

浏览器本地存储

Cookie

Cookie是最早被提出来的本地存储方式,在此之前,服务端是无法判断网络中的两个请求是否是同一用户发起的,为解决这个问题,Cookie就出现了。

Cookie 是存储在用户浏览器中的一段不超过 4 KB 的字符串。它由一个名称(Name)、一个值(Value)和其它几个用 于控制 Cookie 有效期、安全性、使用范围的可选属性组成。

不同域名下的 Cookie 各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的 Cookie 一同发送到服务器。

Cookie的特性

Cookie一旦创建成功,名称就无法修改

Cookie是无法跨域名的,也就是说a域名和b域名下的cookie是无法共享的,这也是由Cookie的隐私安全性决定的,这样就能够阻止非法获取其他网站的Cookie

每个域名下Cookie的数量不能超过20个,每个Cookie的大小不能超过4kb

有安全问题,如果Cookie被拦截了,那就可获得session的所有信息,即使加密也于事无补,无需知道cookie的意义,只要转发cookie就能达到目的

Cookie在请求一个新的页面的时候都会被发送过去

Cookie 在身份认证中的作用

客户端第一次请求服务器的时候,服务器通过响应头的形式,向客户端发送一个身份认证的 Cookie,客户端会自动 将 Cookie 保存在浏览器中。

随后,当客户端浏览器每次请求服务器的时候,浏览器会自动将身份认证相关的 Cookie,通过请求头的形式发送给 服务器,服务器即可验明客户端的身份。

Cookie 不具有安全性

由于 Cookie 是存储在浏览器中的,而且浏览器也提供了读写 Cookie 的 API,因此 Cookie 很容易被伪造,不具有安全性。因此不建议服务器将重要的隐私数据,通过 Cookie 的形式发送给浏览器。

注意:千万不要使用 Cookie 存储重要且隐私的数据!比如用户的身份信息、密码等。

Session

Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了session是一种特殊的cookie。cookie是保存在客户端的,而session是保存在服务端。

为什么要用session

由于cookie 是存在用户端,而且它本身存储的尺寸大小也有限,最关键是用户可以是可见的,并可以随意的修改,很不安全。那如何又要安全,又可以方便的全局读取信息呢?于是,这个时候,一种新的存储会话机制:session 诞生了

session原理

当客户端第一次请求服务器的时候,服务器生成一份session保存在服务端,将该数据(session)的id以cookie的形式传递给客户端;以后的每次请求,浏览器都会自动的携带cookie来访问服务器(session数据id)。

LocalStorage

LocalStorage是HTML5新引入的特性,由于有的时候我们存储的信息较大,Cookie就不能满足我们的需求,这时候LocalStorage就派上用场了。

LocalStorage的优点:

在大小方面,LocalStorage的大小一般为5MB,可以储存更多的信息

LocalStorage是持久储存,并不会随着页面的关闭而消失,除非主动清理,不然会永久存在

仅储存在本地,不像Cookie那样每次HTTP请求都会被携带

LocalStorage的缺点:

存在浏览器兼容问题,IE8以下版本的浏览器不支持

如果浏览器设置为隐私模式,那我们将无法读取到LocalStorage

LocalStorage受到同源策略的限制,即端口、协议、主机地址有任何一个不相同,都不会访问

LocalStorage的常用API

// 保存数据到 localStorage
localStorage.setItem('key', 'value');

// 从 localStorage 获取数据
let data = localStorage.getItem('key');

// 从 localStorage 删除保存的数据
localStorage.removeItem('key');

// 从 localStorage 删除所有保存的数据
localStorage.clear();

// 获取某个索引的Key
localStorage.key(index)

LocalStorage的使用场景

有些网站有换肤的功能,这时候就可以将换肤的信息存储在本地的LocalStorage中,当需要换肤的时候,直接操作LocalStorage即可

在网站中的用户浏览信息也会存储在LocalStorage中,还有网站的一些不常变动的个人信息等也可以存储在本地的LocalStorage中

SessionStorage

SessionStorage和LocalStorage都是在HTML5才提出来的存储方案,SessionStorage 主要用于临时保存同一窗口(或标签页)的数据,刷新页面时不会删除,关闭窗口或标签页之后将会删除这些数据。

SessionStorage与LocalStorage对比:

SessionStorage和LocalStorage都在本地进行数据存储;

SessionStorage也有同源策略的限制,但是SessionStorage有一条更加严格的限制,SessionStorage只有在同一浏览器的同一窗口下才能够共享;

LocalStorage和SessionStorage都不能被爬虫爬取;

SessionStorage的常用API

// 保存数据到 sessionStorage
sessionStorage.setItem('key', 'value');

// 从 sessionStorage 获取数据
let data = sessionStorage.getItem('key');

// 从 sessionStorage 删除保存的数据
sessionStorage.removeItem('key');

// 从 sessionStorage 删除所有保存的数据
sessionStorage.clear();

// 获取某个索引的Key
sessionStorage.key(index)

SessionStorage的使用场景

由于SessionStorage具有时效性,所以可以用来存储一些网站的游客登录的信息,还有临时的浏览记录的信息。当关闭网站之后,这些信息也就随之消除了。

组件的自定义事件

一种组件间通信的方式,适用于:子组件 => 父组件

使用场景

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

绑定自定义事件:

第一种方式

在父组件中使用 <Demo @atguigu="test"/><Demo v-on:atguigu="test"/>

// app.vue
<template>
    <div class="app">
        <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) -->
        <Student @atguigu="getStudentName"/> 
    </div>
</template>

<script>
    import Student from './components/Student'

    export default {
        name:'App',
        components:{Student},
        data() {
            return {
                msg:'你好啊!',
                studentName:''
            }
        },
        methods: {
            getStudentName(name,...params){
                console.log('App收到了学生名:',name,params)
                this.studentName = name
            }
        }
    }
</script>

<style scoped>
    .app{
        background-color: gray;
        padding: 5px;
    }
</style>
// Student.vue
<template>
    <div class="student">
        <button @click="sendStudentlName">把学生名给App</button>
    </div>
</template>

<script>
    export default {
        name:'Student',
        data() {
            return {
                name:'张三',
            }
        },
        methods: {
            sendStudentlName(){
                //触发Student组件实例身上的atguigu事件
                this.$emit('atguigu',this.name,666,888,900)
            }
        },
    }
</script>

<style lang="less" scoped>
    .student{
        background-color: pink;
        padding: 5px;
        margin-top: 30px;
    }
</style>

第二种方式

在父组件中使用 this.$refs.xxx.$on(),这样写起来更灵活,比如可以加定时器啥的。

<Demo ref="xxx"/>
mounted(){
    this.$refs.xxx.$on('mydemo',this.test)    // 利用标识绑定事件
}

若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。

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

使用 this.$emit() 就可以实现子组件向父组件传数据

解绑自定义事件this.$off('atguigu')

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

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

<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) -->
<Student ref="student" @click.native="show"/>

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