Vue学习笔记(二)
非单文件组件:
三大步骤:
-
定义组件(创建组件)
-
注册组件
-
使用组件(写组件标签)
-
定义组件
使用 Vue.extend(options) 创建,其中 options 和 new Vue(options) 时传入的那个 options 几乎一样,但也有点区别:
el 不要写,因为最终所有的组件都要经过一个 vm 的管理,由 vm 中的 el 决定服务哪个容器 data 必须写成函数,为了避免组件被复用时,数据存在引用关系
备注:使用 template 可以配置组件结构
-
注册组件
- 局部注册:靠 new Vue 的时候传入 components 选项
- 全局注册:靠 Vue.component(‘组件名’,组件)
- 编写组件标签
<组件名></组件名>
单文件组件代码:
<!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>
<script src="./js/vue.js"></script>
</head>
<body>
<div id="root">
<school></school>
<hr>
<student></student>
</div>
<script>
Vue.config.productionTip = false
//创建名为 school 的组件
const school = Vue.extend({
template:
`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
`,
data(){
return {
schoolName:'尚硅谷',
address:'北京'
}
}
})
//创建名为 student 的组件
const student = Vue.extend({
template:
`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
studentName:'张三',
age: 18
}
}
})
Vue.component('student',student) //全局指令
new Vue({
el:'#root',
components:{
school, //局部指令
}
})
</script>
</body>
</html>
几个注意点:
-
关于组件名:
一个单词组成:
第一种写法(首字母小写):school 第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):my-school 第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)
备注:
(1)组件名尽可能回避 HTML 中已有的元素名称,例如:h2、H2 都不行 (2)可以使用 name 配置项指定组件在开发者工具中呈现的名字
-
关于组件标签:
第一种写法:<组件名></组件名> 第二种写法:<组件名/> 备注:不使用脚手架时,<组件名/> 会导致后续组件不能渲染
-
一个简写方式:
const school = Vue.extend(options) 可简写为: const school = options
组件的嵌套:
定义一个 app 组件,用来管理所有的组件,最后 app 被 Vue 实例所管理, app 只管它分支下面的组件,在分支中的组件自有分支自己管理,不用写在 app 中 ,代码:
<!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>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="root">
</div>
<script>
Vue.config.productionTip = false
const student = {
template:
`
<div>
<h2>学生名称:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
studentName:'张三',
age: 18
}
}
}
const school = {
template:
`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>
`,
data(){
return {
schoolName:'尚硅谷',
address:'北京'
}
},
components:{
student
}
}
const hello = {
template:`<h2>{{msg}}</h2>`,
data(){
return {
msg: 'hello'
}
}
}
const app = {
template:
`
<div>
<school></school>
<hello></hello>
</div>
`,
components:{
school,
hello
}
}
new Vue({
el:'#root',
template:`<app></app>`,
components:{
app
}
})
</script>
</body>
</html>
其中我们可以看到在 school 组件中写了 components:{ student },说明 student 组件是嵌套在 school 组件中的,归 school 组件管理,而 app 组件中 components 下有两个组件名,说明它们是平级的,且归 app 管理
componet函数
-
school 组件本质是一个名为 VueComponent 的构造函数,且不是程序员定义的,是 Vue.extend 生成的
-
我们只需要写 或 ,Vue 解析时会帮我们创建 school 组件的实例对象,即 Vue 帮我们执行的: new VueComponent(options)
-
特别注意:每次调用 Vue.extend 返回的都是一个全新的 VueComponent
-
关于 this 指向:
(1)组件配置中:
data 函数、methods 中的函数、watch 中的函数、computed 中的函数 它们的 this 均是【VueComponent 实例对象】
(2)new Vue() 配置中:
data 函数、methods 中的函数、watch 中的函数、computed 中的函数 它们的 this 均是【Vue 实例对象】
- VueComponent 的实例对象称之为组件实例对象
一个重要的内置关系:
VueComponent.prototype.proto === Vue.prototype
组件是可复用的Vue实例,data必须写成函数
为什么要有这个关系: 让组件实例对象可以访问到 Vue 原型上的属性、方法
可能这么说不理解,配个图!
单文件组件:
< v 这两个字符可以自动配置好vue的结构
<template>
<div class="demo">
<h2>姓名:{{name}}</h2>
<h2>家庭地址:{{address}}</h2>
<button @click="showName">点我提示当前名称</button>
</div>
</template>
<script>
export default {
name:'School',
data(){
return {
name:'张三',
address:'北京'
}
},
methods: {
showName(){
alert(this.name)
}
},
}
</script>
<style>
.demo{
background-color: orange;
}
</style>
vue脚手架:command line interface Cli
npm config set cache=“D:\Program Files (x86)\nodejs\node_cache”
原来node.js就是来配置npm的,有了npm之后才可以运行vue的文件
vue的目录还是很简单的
分析render函数:
render 函数 跟 template 一样都是创建 html 模板的,但是有些场景中用 template 实现起来代码冗长繁琐而且有大量重复,这时候就可以用 render 函数。
官网例子:子组件想要根据父组件传递的 level 值(1-6)来决定渲染标签 h 几。具体代码可以看文档。
render 函数讲解
render 函数即渲染函数,它是个函数,它的参数也是个函数——即 createElement,我们重点来说 createElement 参数。
render 函数的返回值(VNode)
VNode(即:虚拟节点),也就是我们要渲染的节点。
render 函数的参数(createElement)
createElement 是 render 函数 的参数,它本身也是个函数,并且有三个参数。
createElement 函数的返回值(VNode)
createElement 函数的返回值是 VNode(即:虚拟节点)。
createElement 函数的参数(三个)
一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数。类型:{String | Object | Function}。必需。
一个包含模板相关属性的数据对象你可以在 template 中使用这些特性。类型:{Object}。可选。
子虚拟节点 (VNodes),由 createElement() 构建而成,也可以使用字符串来生成“文本虚拟节点”。类型:{String | Array}。可选。
/**
* render: 渲染函数
* 参数: createElement
* 参数类型: Function
*/
render: function (createElement) {
let _this = this['$options'].parent // 我这个是在 .vue 文件的 components 中写的,这样写才能访问this
let _header = _this.$slots.header // $slots: vue中所有分发插槽,不具名的都在default里
/**
* createElement 本身也是一个函数,它有三个参数
* 返回值: VNode,即虚拟节点
* 1. 一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数。必需参数。{String | Object | Function} - 就是你要渲染的最外层标签
* 2. 一个包含模板相关属性的数据对象你可以在 template 中使用这些特性。可选参数。{Object} - 1中的标签的属性
* 3. 子虚拟节点 (VNodes),由 `createElement()` 构建而成,也可以使用字符串来生成“文本虚拟节点”。可选参数。{String | Array} - 1的子节点,可以用 createElement() 创建,文本节点直接写就可以
*/
return createElement(
// 1. 要渲染的标签名称:第一个参数【必需】
'div',
// 2. 1中渲染的标签的属性,详情查看文档:第二个参数【可选】
{
style: {
color: '#333',
border: '1px solid #ccc'
}
},
// 3. 1中渲染的标签的子元素数组:第三个参数【可选】
[
'text', // 文本节点直接写就可以
_this.$slots.default, // 所有不具名插槽,是个数组
createElement('div', _header) // createElement()创建的VNodes
]
)
}
总的来说就是runtime时候的Vue版本和开发的Vue版本是不一样的,runtime时候的Vue版本不包含模板的渲染,即不包含temp选项
webpack
(68条消息) Webpack的基本使用_sut_uestc的博客-CSDN博客
前端模块化的一些方案:AMD、CMD、CommonJS、ES6(浏览器不能识别它们,但是webpack可以做它们的底层支撑,方可进行模块化开发)
ES6之前,要想进行模块化开发,就必须借助于其他的工具,让我们可以进行模块化开发
并且在通过模块化开发完成了项目后,还需要处理模块化间的各种依赖,并且将其进行整合打包
此时出现webpack,其中一个核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的依赖关系。
而不仅仅是JavaScript文件,我们的CSS、图片、json文件等等在webpack中都可以被当做模块来使用
脚手架文件结构:
├── 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可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh
ref标签:
ref属性
被用来给元素或子组件注册引用信息(id的替代者)
应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
使用方式:
打标识:
…
或获取: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中的数据。npm
传进来的props是没有办法去修改的
都是vc先去准备生成的,然后利用生成的vc去渲染已经有的vm
Vue代码关闭语法检查:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false//关闭语法检查
})
export
在JavaScript ES6中,export与export default均可用于导出常量、函数、文件、模块等,你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方式,将其导入,以便能够对其进行使用,但在一个文件或模块中,export、import可以有多个,export default仅有一个。
具体使用:
———————————————
//demo1.js
export const str = 'hello world'
export function f(a){
return a+1
}
//导入方式
//demo2.js
import { str, f } from 'demo1' //也可以分开写两次,导入的时候带花括号
//demo1.js
export default const str = 'hello world'
//demo2.js
import str from 'demo1' //导入的时候没有花括号
mixin混入:
-
功能:可以把多个组件共用的配置提取成一个混入对象
-
使用方式:
第一步定义混合:
const mixin = {
data(){....},
methods:{....}
....
}
第二步使用混入:
全局混入:Vue.mixin(xxx)
局部混入:mixins:['xxx']
混入的时候,如果原来的位置有混入的值的话,以原来的数值为主
scoped用法:
- 作用:让样式在局部生效,防止冲突。
- 写法:
<style scoped>
APP里面去写样式,一般不会使用scoped修饰
这个lan表示的是language,不写的话默认的是CSS
ToDoList案例(未完成)
浏览器本地存储 localstorage和sessionStorage:
1.存储内容大小一般支持5MB左右(不同浏览器可能还不-样)
2.浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制。
3.相关API:
- xxxxxStorage . setItem(‘key’, ‘value’);
该访法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。 - xxxxxStorage. getItem(’ person’);
该访法接受一个键名作为参数,返回键名对应的值。 - xxxxxStorage. removeItem(‘key’ );
该方法接受一个键名作为参数, 并把该键名从存储中删除。 - xxxStorage. clear()
该方法会清空存储中的所有数据。
4.备注: - SessionStorage存储的内容会随着浏览器窗口关闭而消失。
- LocalStorage存储的内容,需要手动清除才会消失。
- xxxxStorage. getItem(xx)如果xxx对应的value获取不到,那么gettem的返回值是null。
- JSON. parse(null)的结果依然是null.
(70条消息) cookie、sessionStorage,localStorage区别_年轻即出发的博客-CSDN博客
(70条消息) cookie、sessionStorage和localStorage的区别_浮生离梦的博客-CSDN博客_localstorage和sessionstorage和cookie
组件的自定义事件
(71条消息) vue中组件的自定义事件(详)_suoh’s Blog的博客-CSDN博客_vue 组件事件
解绑事件:
组件的自定义事件
1.种组件间通信的方式,适用于:子组件= =>父组件
2.使用场景: A是父组件, B是子组件, B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
3.绑定自定义事件:
1.第一种方式,在父组件中:
<Demo @atguigu="test"/> <Demo v-on:atguigu="test"/>
2.第二种方式,在父组件中:
<Demo ref=" demo"/>
mounted( ){
this . $refs . x $on('atguigu' ,this.test)
3.若想让自定义事件只能触发- -次, 可以使用once修饰符,或$once方法。
4.触发自定义事件: this. $emit(’ atguigu’ ,数据)
5.解绑自定义事件this. $off( ’ atguigu’)
6.组件上也可以绑定原生DOM事件,需要使用native修饰符。
7.注意:通过this. $refs . xx. $on( ‘atguigu’,回调)绑定自定义事件时,回调要么配置在methods中, 要么用箭头函数,否则this指向会出问题!
全局事件总线:
任意事件之间的通信:
安装全局事件总线:
Vue组件当中:
其他组件的代码:
总结:
全局事件总线 (GlobalEventBus)
1.一种组件间通信的方式,适用于任意组件间通信。
2.安装全局事件总线:
new Vue({
beforeCreate() {
Vue. prototype.$bus = this //安装全局事件总线,$bus就是当 前应用的vm
})
3.使用事件总线:
1.接收数据: A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){
demo(data){......}
}
mounted() {
this . $bus . $on( ' xxxx' ,this . demo)
}
2.提供数据: this . $bus. e m i t ( ′ x x x x ′ , 数据 ) 4. 最好在 b e f o r e D e s t r o y 钩子中,用 emit( 'xxxx' ,数据) 4.最好在beforeDestroy钩子中,用 emit(′xxxx′,数据)4.最好在beforeDestroy钩子中,用off去解绑当前组件所用到的事件。