let、var、const
(1) var
在 ES6 出现之前,var 声明占主导地位。但是,使用 var 声明的变量存在一些问题。
- var 声明的作用域是全局的或函数/局部的
当 var 变量在函数外部声明时,作用域是全局的。这意味着在函数体外用 var 声明的任何变量都可以在整个窗口中使用。
var 在函数中声明时,它的作用域是在函数体内。这意味着它只能在该函数中被访问。 - var 变量可以重新声明和更新
这意味着我们可以在相同的作用域内执行此操作,并且不会出错。
var greeter = "hey hi";
var greeter = "say Hello instead";
var greeter = "hey hi";
greeter = "say Hello instead";
- var 的提升
console.log (greeter);
var greeter = "say hello"
解释为
var greeter;
console.log(greeter); // greeter is undefined
greeter = "say hello"
- val的问题
var greeter = "hey hi";
var times = 4;
if (times > 3) {
var greeter = "say Hello instead";
}
console.log(greeter) // "say Hello instead"
(2) let
- let 是块作用域
let greeting = "say Hi";
let times = 4;
if (times > 3) {
let hello = "say Hello instead";
console.log(hello);// "say Hello instead"
}
console.log(hello) // hello is not defined
- let 可以更新但不能重新声明
let greeting = "say Hi";
greeting = "say Hello instead"; // error: Identifier 'greeting' has already been declared
但是,如果同一个变量定义在不同的作用域,就不会报错
let greeting = "say Hi";
if (true) {
let greeting = "say Hello instead";
console.log(greeting); // "say Hello instead"
}
console.log(greeting); // "say Hi"
就像 var 一样,let 声明被提升到顶部。与初始化为 undefined 的 var 不同,let 关键字未初始化。所以如果你在声明之前尝试使用 let 变量,你会得到一个 Reference Error。
(3) const
与 let 声明一样,const 声明只能在它们声明的块内访问。
每个 const 声明都必须在声明时进行初始化。
const 不能更新或重新声明。
const greeting = "say Hi";
greeting = "say Hello instead";// error: Assignment to constant variable.
const greeting = "say Hi";
const greeting = "say Hello instead";// error: Identifier 'greeting' has already been declared
const greeting = {
message: "say Hi",
times: 4
}
greeting = {
words: "Hello",
number: "five"
} // error: Assignment to constant variable.
greeting.message = "say Hello instead"; //这样是允许的
=== 与 =
- ===
严格相等(三个等号)
比较两个操作数时,如果类型不同,就一定不相等
(1)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等
(2)如果两个值都是true,或是false,那么相等
(3)如果两个值都引用同一个对象或是函数,那么相等,否则不相等
(4)如果两个值都是null,或是undefined,那么相等 - ==
宽松相等(两个等号)
比较两个操作数时
如果两个类型不同,双等号(==)将执行类型转换,有可能会返回相等
(1)如果一个是null,一个是undefined,那么相等
(2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较
Vue Chrome浏览器调试插件Devtools
// 开发环境,包含完整的警告和调试模式
<script type="text/javascript" src="./js/vue.js"></script>
// 生成环境
<script type="text/javascript" src="./js/vue.min.js"></script>
容器与vue绑定
<input id = "root" v-bind:value="name"></input>
<input id = "root2" v-model:value="age"></input>
<script>
vm = new Vue({
el: '#root2',
data: {
name: '简书',
age: 18
}
})
vm2 = new Vue({
el: '#root2',
data: {
name: '简书',
age: 18
}
})
<script>
//容器与vue是一 一绑定,即多个vue对象不能绑定同一个容器
//(1) root输入框容器与vue单向绑定,即vue的data数据更新会同步更新到容器,而容器的输入值修改不会同步更新到vue的data数据
//(2) root2输入框容器与vue双向绑定,即vue的data数据更新会同步更新到容器,容器的输入值修改也会同步更新到vue的data数据
<div id = 'root'>{{name}}<div>
var data = {
name: '简书',
age: 18,
}
vm = new Vue({
data: data,
method: {
showinfo: funtion(){
console.log(this) //this为 vue对象
},
//showinfo(){ //简写方式
//}
//showinfo: ()=>{ //箭头函数
// console.log(this) //this不为vue对象,为windows
//}
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// 实例化vue对象时没有绑定容器,而是实例化之后进行绑定
vm.$mount('#root')
vm._data === data
vm.name == data.name
插值法与指令语法
- 插值法
{{name}},用于html标签体,即<div>{{name}}</div> - 指令语法
v-bind 指令,用于标签属性,v-bind:可以简写为:, 如 v-bind:value,可以简写为:value
v-model 指令,用于表单类型元素,如 v-model:value,可以简写为v-model
v-if 指令, <p v-if='seen'>现在你看到我了</p>,当seen=true时,才展示
v-else-if指令、v-else
v-for 指令, <li v-for='book in books'>{{book}}</li>
v-on 指令,可以简写为@,如 v-on:click,可以简写为@click
v-show指令,控制是否显示,映射样式的display 如:style='display:none'
v-text指令,<div v-text='name'>这里输入内容失效</div>与<div>{{name}}</div>等价,如果name='<h1>test</h1>' v-text不解析html标签,内容原样显示
v-html指令,作用v-text差不多,与v-text区别,v-html指令会解析内容里面的标签
<template v-if><h1>aa</h1></h2>bb</h2></template> 模版与v-if配合
vm = new Vue({
el: '#root',
data: {
name: '简书',
age: 18,
seen: true
books: ['book1','book2']
}
})
修饰符:
// .prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault(),即只执行事件处理函数,不提交到服务器端
<form v-on:submit.prevent="onSubmit">...</form>
绑定class样式
:class属性值由vue解析出来的样式会与class属性定义的样式合并
<div id = 'root'>
<div class = 'basic' :class='style' @click='changStyle'>test</div>
//<div class = 'basic' :class="['normal','happy']" >test2</div>
<div class = 'basic' :class='arr' @click='changStyle2'>test2</div>
<div class = 'basic' :class='classObj' >test3</div>
<div class = 'basic' :style='styleObj' >test4</div>
<div>
<script>
vm = new Vue({
el: '#root',
data: {
name: '简书',
age: 18,
style: 'normal',
arr: ['style1','style2'],
classObj: {
'normal': true,
'happy': false
},
styleObj:{
fontSize: '40px'
}
},
methods:{
changStyle(){
this.style = 'happy'
},
changStyle2(){
this.arr.shift()
}
}
})
</script>
computed计算属性
计算属性会缓存,get函数什么时候调用?1、初次读取计算属性时,2、当依赖的属性发生变化时候,get函数会重新调用
计算属性使用{{fullName}}
computed:{
fullName: {
get(){
}
set(){
}
}
}
当计算属性只有get函数时,简写为下面形式:
computed:{
fullName(){
}
}
style scope
组件的style加 scope防止组件定义的class样式与其它组件的class名称相同导致冲突
<style scope>
</style>
app组件的style一般不会定义为scope,这里定义的class样式为所有组件共享的样式
语言默认为css,如果要使用less,需要配置lang='less',使用前需要npm -i less-loader@7(不加版本,默认是最新的,最新的less是需要配合webpack的5版本)
<style lang='less'>
</style>
:key 唯一标识(虚拟DOM,Vue使用,在真实DOM中不存在)
自定义指令
<div id= root>
<h2>{{name}}</h2>
<h2>当前n的值<span v-text="n"></span></h2>
<h2>放到十倍后的值<span v-big="n"></span></h2>
</div>
<script>
vm = new Vue({
el: '#root',
data: {
name: '简书',
age: 18,
n: 1
},
directives:{
// big函数何时会被调用 1、指令与元素成功绑定时 2、指令所在模版被重新解析(有变量变化就会引起模版解析)
big(element, binding){
element.innerText = binding.value*10
},
fbind: {
// 指令与元素成功绑定
bind(element, binding){
element.innerText = binding.value
},
// 指令所在元素被插入页面
inserted(element, binding){
element.foucus()
},
// 指令所在模版被重新解析
updated(element, binding){
element.innerText = binding.value
}
}
}
})
</script>
表单
// 修饰符阻止默认行为,不提交调整了
<form @submit.prevent='showInfo'>
<input type='text' v-model.trim='username'/>
<input type='password' v-model='password'/>
// number修饰符
<input type='number' v-model.number='age'/>
<input type='radio' name='sex' v-model='sex' value='male'/>
<input type='radio' name='sex' v-model='sex' value='female'/>
// 如果没有配置value属性,收集的是checked属性
<input type='checkbox' v-model='hobby' value='study'/>
<input type='checkbox' v-model='hobby' value='game'/>
<select v-model='city'>
<option value=''>请选择</option>
<option value='beijing'>北京</option>
<option value='shanghai'>上海</option>
</select>
//延迟收集,失去焦点收集
<input type='text' v-model.lazy='other'/>
</form>
<script>
const vm = new Vue({
el: '#root',
data: {
username: '',
password: '',
sex: 'male',
hobby: [] //类型必须为数组,如果定义为'',会影响数据收集,收集的为true或false
city: 'beijing',
other: ''
},
methods:{
showinfo(){
alert('ok')
}
}
})
</script>
组件
实现应用中局部功能的代码和资源的集合
非单文件组件:一个文件包含多个组件
单文件组件:一个文件只包含一个组件(vue文件)
1、创建组件 2、注册组件
<div id= 'root'>
// 使用组件
<school></school>
<hr>
<student></student>
</div>
<script>
const school = Vue.extend({
// 组件不能写el,因为组件可以公用
// el: '#root',
template: '<div><h1>{{schoolName}}</h1><h1>{{address}}</h1></div>'
// data只能用这种写法
data(){
return {
schoolName: 'a',
address: 'xxx'
}
}
})
const student= Vue.extend({
//开发者工具呈现名字
name: 'school',
// 组件不能写el,因为组件可以公用
// el: '#root',
template: '<div><h1>{{studentName}}</h1><h1>{{age}}</h1></div>'
// data只能用这种写法
data(){
return {
studentName: 'b',
age: 18
}
}
})
const vm= new Vue({
el: '#root',
// 局部注册
components:{
school: school,
student: student
}
})
//全局注册
Vue.component('hello',hello)
</script>
VueComponent构造函数
### 数据代理
```javascript
var data = { name: '简书' }
// var data = { name: '简书' , age: 20} 直接在这里定义的sex属性默认是可以修改的
const vm = new Vue({
el: '#root',
data: data
})
Object.defineProperty(data, 'age',{
configurable: true, // 属性是否可删除,默认为false
writable: true, //属性值是否可以修改,默认为false
enumerable: true, //属性key是否可枚举,默认false,类似for key in data console.log(key) 、Object.keys()不会输出sex属性
value: 18,
get: funtion(){ // getter
return vm.age
},
set: funtion(val){ //setter
vm.age= val
}
})
MVVM
image.pngM 代表Model,即模型,plain javascript objects
V 代表View, 即模版视图,DOM
VM代表 View Model,Vue
Model用纯JavaScript对象表示,View负责显示,两者做到了最大限度的分离。
ViewModel把Model和View关联起来。ViewModel负责通过Data bindings把Model的数据同步到View显示出来,还负责通过DOM Listeners(监听view的修改)把View的修改同步回Model
安装vue-cli
//全局安装
npm install -g @vue/cli
npm config set registry https://registry.npm.taobao.org
vue create my-project
// 运行
npm run serve
babel,es6转es5
export
ctrl + s,更新代码
vue核心 + 模版
esm:es module
common.js
render
new Vue({
router,
render: h => h(App),
}).$mount('#app')
vue ref
给html元素或子组件注册引用信息
<template>
<h1 v-text='msg' ref='title'></h1>
</template>
<script>
this.$refs.title
</script>
### props
<School name='张三' sex='男' age='18>
student= {
//开发者工具呈现名字
name: 'school',
//props: ['name','sex','age'] //简单接收
/*
props:{
name: String,
sex: String,
age: Number
},
*/
props{
name{
type: String,
required: true
},
sex{
type: String,
required: true
},
age{
type: Number,
required: true,
default: 19
},
}
}
mixin 混入
多个组件共用配置提取为一个混入对象,使用混入
mixin.js
export const henru1 = {
data:{},
methods:{},
mounted(){
}
}
全局混合:在app组件 import 混入 Vue.mixin(henru1) Vue.mixin(henru2)
局部混入: 在vc的mixins:[henru1,henru2]
插件plugin
export default{
install(Vue,options){
Vue.filter(..)
Vue.directive(..)
Vue.mixin(..)
Vue.prototype.$myMethod = function(){...}
Vue.prototype.$myProperty = xxx
}
}
// 传入多个参数
Vue.use(plugins,1,2)
插槽 slot
默认插槽
<category>
<image src=''></image>
</category>
category组件:
<template>
<h1>测试</h1>
<slot>默认</slot>
</template>
具名插槽:
<category><image slot="center" src=''></image><a slot="footer"/></category>
或
<category>
<template slot="center">//或<template v-slot:center> 只有template元素才能用这种写法
<image src=''></image>
</template>
<a href='' slot="footer"/>
</category>
category组件:
<template>
<h1>测试</h1>
<slot name="center">默认</slot>
<slot name="footer">默认</slot>
</template>
作用域插槽:
数据在组件,需要把数据传给使用插槽的地方
<category>
<template scope = '{games}'> //或者使用slot-scope 必须使用template包裹,{games}是结构赋值,如果<template scope = 'xx'>,那使用games就必须通过xx.games
</template >
</category>
category组件:
<template>
<slot :games="games" msg="hello">默认</slot> //可以传多个数据给组件的使用者
</template>
$emit
组件自定义事件
使用组件地方
<Student v-on:test="getName" ref="student"/>
new Vue(){
methods:{
getName(){
}
mounted(){
this.$refs.student.$on('test',this.getName);
}
}
}
Student组件定义:
<h1>student组件</h1>
<button @click="sendName"></button>
export default {
methods:{
sendName(){
this.$emit('test','xx');
}
}
}
也可以通过off('test'); //解绑事件 this.$off(['test'])
...param,接收多个参数
sync修饰符
在父组件上告诉子组件传递过去的msg跟父组件上的n保持同步,相当于允许它修改
<child :msg.sync='n'></child> //msg属性
<button @click="$emit('update:msg',msg-1)">子组件点击{{msg}}</button>
vuex
多组件数据共享:全局事件总线实现
vm store配置项
action:{}、mutation: {}、state: {}
route
export default new VueRouter({
router:[
{
path: '/about',
component: about
},
{
path: '/home',
component: home
}
]
})
<route-link to='/about' active-class='active'>
<route-view></route-view>
路由守卫
{
path: '/home',
component: Home,
meta: {title:'', isAuth:true}
}
-
全局路由守卫(针对所有路由)
// 初始化的时候调用、每次路由被切换之前被调用
// to代表要切换到哪个路由,from代表从哪个路由来
router.beforeEach(to,from,next){
//next()
})
// 初始化的时候调用、每次路由被切换之后被调用
router.afterEach(to,from){
} -
独享路由守卫(只有一个)
{
path: '/home',
component: Home,
// 进入之前
beforeEnter: (to, from, next) =>{
}
} -
组件内路由守卫
export default {
name: 'Student',
data(){
return {}
},
// 通过路由规则,进入该组件时被调用
beforeRouteEnter(to, from, next){
},
// 通过路由规则,离开该组件时被调用
beforeRouteLeave(to, from, next){
}
}
路由的两个生命周期钩子
//组件激活
activated(){
}
//组件失活
deactivated(){
}
数据劫持
ES6与ES5
<script type='module'/>
export:
(1)分别暴露
export function(){}
(2)统一暴露
export {}
(3)默认暴露
export default
import:
通用导入
import * as m1 from ''; ////分别暴露、统一暴露、默认暴露
解构赋值形式
import {} from ''; //分别暴露和统一暴露
import {default as x} from ''; //默认暴露
简便形式:
import x from ''; //默认暴露
<script src='' type='module'/>
网友评论