1.es6语法
const let
includes startsWith endsWith
解构表达式:数组 const [x,y,z] = arr 对象 const {name:a, age:b}=person
函数优化: 1.赋默认值 2.箭头 ()=>{} 3.对象 play(){}
map(fun):处理数组中的每一个元素放入新的数组
reduce((a,b)=>a+b, 100):
keys values entries
assign(dest, ...src): 前拷贝
find() findIndex includes
2. MVVM
M:数据模型
V:视图渲染的模板
vm:视图和模型的映射关系,vue
3. vue程序
html模板
声明式渲染:
{{数据模型}}: 插值闪烁
v-text:
v-html: 解析数据模型中的html元素
双向渲染:
v-model=数据模型:在form表单元素中使用才有意义
事件:v-on 简写:@
@click:点击事件
@contextMenu.prevent:右击事件
@keyup.enter: 回车事件
v-for: 遍历数组或者对象,比v-if执行优先级更高
数组:v-for="(item,index) in items"
对象:v-for="(val, key, index) in user"
key:提高渲染效率
v-if: 判断
v-if="布尔表达式" : false-不再渲染 true-渲染
v-show="布尔表达式" : 都会渲染 false-隐藏
v-else-if v-else
v-bind: 绑定属性,简写冒号
:class="{active: 布尔表达式}"
vue实例
el:选择器
data:数据模型
methods:定义方法
created():vue实例初始化之后执行,初始化数据
computed:计算属性,跟方法类似,但是所有的方法必须有返回值,可以像数据模型一样使用,基于依赖的数据模型进行缓存
watch:监控,定义监控方法,方法名跟被监控的数据模型名一致 两个参数:newVal oldVal
4. 组件
全局组件: 通过Vue的component方法来定义一个全局组件。
<div id="app">
<!--使用定义好的全局组件-->
<counter></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
// 定义全局组件,两个参数:1,组件名称。2,组件参数
Vue.component("counter",{
template:'<button v-on:click="count++">点击 {{ count }} 次.</button>',
data(){//组件中的数据模型通过data(){}指定而不是data:属性
return {
count:0
}
}
})
var app = new Vue({
el:"#app"
})
</script>
[注]:
- 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
- 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
- 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
- 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
- data必须是一个函数,不再是一个对象,为了实现复用,每个实例可以维护一份被返回对象的独立的拷贝,每个组件互不干扰
<div id="app">
<!--使用定义好的全局组件-->
<counter></counter>
<counter></counter>
<counter></counter>
</div>
局部组件:
一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。因此,对于一些并不频繁使用的组件,我们会采用局部注册。
先在外部定义一个对象,结构与创建组件时传递的第二个参数一致:
const counter = {
template:'<button v-on:click="count++">了{{ count }} 次.</button>',
data(){
return {
count:0
}
}
};
然后在某个Vue实例中使用它:
var app = new Vue({
el:"#app",
components:{
counter:counter // 将定义的对象注册为组件
}
})
- components就是当前vue对象子组件集合。
- 其key就是子组件名称
- 其值就是组件对象名
- 效果与刚才的全局注册是类似的,不同的是,这个counter组件只能在当前的Vue实例中使用
5. 组件通信
通常一个单页应用会以一棵嵌套的组件树的形式来组织: - 页面首先分成了顶部导航、左侧内容区、右侧边栏三部分
- 左侧内容区又分为上下两个组件
- 右侧边栏中又包含了3个子组件
各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求
父向子传递
- 父组件使用子组件时,自定义属性(属性名任意,属性值为要传递的数据)
- 子组件通过props接收父组件数据,通过自定义属性的属性名 父组件使用子组件,并自定义了title属性
<div id="app">
<h1>打个招呼:</h1>
<!--使用子组件,同时传递title属性-->
<introduce title="大家好,我是飞哥"/>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component("introduce",{
// 直接使用props接收到的属性来渲染页面
template:'<h1>{{title}}</h1>',
props:['title'] // 通过props来接收一个父组件传递的属性
})
var app = new Vue({
el:"#app"
})
</script>
props验证
定义一个子组件,并接收复杂数据:
const myList = {
template: '\
<ul>\
<li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\
</ul>\
',
props: {
items: {
type: Array,
default: [],
required: true
}
}
};
- 这个子组件可以对 items 进行迭代,并输出到页面。
- props:定义需要从父组件中接收的属性
- items:是要接收的属性名称
- type:限定父组件传递来的必须是数组
- default:默认值
- required:是否必须 当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告
- props:定义需要从父组件中接收的属性
在父组件中使用它:
<div id="app">
<h2>语言:</h2>
<!-- 使用子组件的同时,传递属性,使用了v-bind,指向了父组件自己的属性lessons -->
<my-list :items="lessons"/>
</div>
var app = new Vue({
el:"#app",
components:{
myList // 当key和value一样时,可以只写一个
},
data:{
lessons:[
{id:1, name: 'java'},
{id:2, name: 'php'},
{id:3, name: 'ios'},
]
}
})
动态静态传递
给 prop 传入一个静态的值:
<introduce title="大家好,我是fly哥"/>
给 prop 传入一个动态的值: (通过v-bind从数据模型中,获取title的值)
<introduce :title="title"/>
静态传递时,传入的值都是字符串类型的,但实际上任何类型的值都可以传给一个 props
<!-- 即便 `42` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个JavaScript表达式而不是一个字符串。-->
<blog-post v-bind:likes="42"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:likes="post.likes"></blog-post>
子向父的通信:$emit
案例:
<div id="app">
<h2>num: {{num}}</h2>
<!--使用子组件的时候,传递num到子组件中-->
<counter :num="num"></counter>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
Vue.component("counter", {// 子组件,定义了两个按钮,点击数字num会加或减
template:'\
<div>\
<button @click="num++">加</button> \
<button @click="num--">减</button> \
</div>',
props:['num']// count是从父组件获取的。
})
var app = new Vue({
el:"#app",
data:{
num:0
}
})
</script>
- 子组件接收父组件的num属性
- 子组件定义点击按钮,点击后对num进行加或减操作 运行发现浏览器端报错,子组件接收到父组件属性后,默认是不允许修改的。 既然只有父组件能修改,那么加和减的操作一定是放在父组件:
var app = new Vue({
el:"#app",
data:{
num:0
},
methods:{ // 父组件中定义操作num的方法
increment(){
this.num++;
},
decrement(){
this.num--;
}
}
})
但是,点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数.可以通过v-on指令将父组件的函数绑定到子组件上:
<div id="app">
<h2>num: {{num}}</h2>
<counter :count="num" @inc="increment" @dec="decrement"></counter>
</div>
在子组件中定义函数,函数的具体实现通过调用Vue内置的this.$emit()函数,调用父组件绑定的函数实现,并在子组件的HTML模板中调用这些函数。当子组件模板中按钮被点击时,调用绑定的函数:
Vue.component("counter", {
template:'\
<div>\
<button @click="plus">加</button> \
<button @click="reduce">减</button> \
</div>',
props:['count'],
methods:{
plus(){
this.$emit("inc");
},
reduce(){
this.$emit("dec");
}
}
})
6. 路由vue-router
场景模拟
如果要实现这样一个功能:
一个页面,包含登录和注册,点击不同按钮,实现登录和注册页切换:
(1)新建index.html:
<div id="app">
<span>登录</span>
<span>注册</span>
<hr/>
<div>
登录页/注册页
</div>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
el:"#app"
})
</script>
(2) 实现登录组件,以前都是写在一个文件中,但是为了复用性,开发中都会把组件放入独立的JS文件中,新建一个user目录以及login.js及register.js:
编写组件,只写HTML模板,不写功能。
login.js内容如下:
const loginForm = {
template:'\
<div>\
<h2>登录页</h2> \
用户名:<input type="text"><br/>\
密码:<input type="password"><br/>\
</div>\
'
}
register.js内容(&ensp一个汉字,&emsp半个汉字):
const registerForm = {
template:'\
<div>\
<h2>注册页</h2> \
用 户 名:<input type="text"><br/>\
密  码:<input type="password"><br/>\
确认密码:<input type="password"><br/>\
</div>\
'
}
在父组件中引用:
<div id="app">
<span>登录</span>
<span>注册</span>
<hr/>
<div>
<!--<loginForm></loginForm>-->
<!--
为什么不采用上面的写法?
由于html是大小写不敏感的,如果采用上面的写法,则被认为是<loginform></loginform>
所以,如果是驼峰形式的组件,需要把驼峰转化为“-”的形式
-->
<login-form></login-form>
<register-form></register-form>
</div>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script src="user/login.js"></script>
<script src="user/register.js"></script>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
components: {
loginForm,
registerForm
}
})
</script>
想要的效果是:当点击登录或注册按钮,分别显示登录页或注册页,而不是一起显示。但是,如何才能动态加载组件,实现组件切换?虽然使用原生的Html5和JS也能实现,但是官方推荐使用vue-router模块。 使用NPM安装:
npm install vue-router --save
在首页index.htm中引入依赖:
<script src="../node_modules/vue-router/dist/vue-router.js"></script>
新建vue-router对象,并且指定路由规则:
// 创建VueRouter对象
const router = new VueRouter({
routes:[ // 编写路由规则
{
path:"/login", // 请求路径,以“/”开头
component:loginForm // 组件名称
},
{
path:"/register",
component:registerForm
}
]
})
- 创建VueRouter对象,并指定路由参数
- routes:路由规则的数组,可以指定多个对象,每个对象是一条路由规则,包含以下属性:
- path:路由的路径
- component:组件名称 在父组件中引入router对象:
var vm = new Vue({
el:"#app",
components:{// 引用登录和注册组件
loginForm,
registerForm
},
router // 引用上面定义的router对象
})
页面跳转控制:
<div id="app">
<!--router-link来指定跳转的路径-->
<span><router-link to="/login">登录</router-link></span>
<span><router-link to="/register">注册</router-link></span>
<hr/>
<div>
<!--vue-router的锚点,用于渲染HTML模板-->
<router-view></router-view>
</div>
</div>
- 通过来指定一个锚点,当路由的路径匹配时,vue-router会自动把对应组件放到锚点位置进行渲染
- 通过指定一个跳转链接,当点击时,会触发vue-router的路由功能,路径中的hash值会随之改变 【注】单页应用中,页面的切换并不是页面的跳转。仅仅是地址最后的hash值变化。事实上,总共就一个HTML:index.html