1.1 过滤器:
在js中使用filters设置,运用‘item|过滤器’
1.2 v-model:
v-model指令可以实现表单元素和数据的双向绑定,如:动态得到输入框(input、textarea)的值
v-model其实是一个语法糖,它的背后本质上是包含两个操作:
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
1.2.1 v-model案例
单选框<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-model结合radio</title>
</head>
<body>
<div id="app">
<!-- 使用name使单选框只能选一个-->
<label for="male">
<input type="radio" id="male" name="sex" value="男" v-model="sex">男
</label>
<label for="female">
<input type="radio" id="female" name="sex" value="女" v-model="sex">女
</label>
<br>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
sex: '男'
}
})
</script>
</body>
</html>
复选框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-model结合checkbox</title>
</head>
<body>
<div id="app">
<!-- checkbox单选框 -->
<!-- <label for="license">-->
<!-- <input type="checkbox" id="license" v-model="isAgree">同意协议-->
<!-- </label>-->
<!-- <h2></h2>-->
<!-- <button :disabled="!isAgree">下一步</button>-->
<!-- <br>-->
<!-- -->
<!-- checkbox多选框 -->
<input type="checkbox" value="篮球" v-model="hobbies">篮球
<input type="checkbox" value="足球" v-model="hobbies">足球
<input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
<input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
<input type="checkbox" value="网球" v-model="hobbies">网球
<br>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊',
isAgree: false,//单选框
hobbies: []//多选框
}
})
</script>
</body>
</html>
1.2.2 v-model修饰符
lazy修饰符:
默认情况下,v-model默认是在input事件中同步输入框的数据的。 也就是说,一旦有数据发生改变对应的data中的数据就会自动发生改变。lazy修饰符可以让数据在失去焦点或者回车时才会更新
number修饰符:
默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。 但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。number修饰符可以让在输入框中输入的内容自动转成数字类型
trim修饰符:
如果输入的内容首尾有很多空格,通常我们希望将其去除trim修饰符可以过滤内容左右两边的空格
1.3 组件化
1.3.1 概念
如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。但如果,我们将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。
1.3.2 注册组件的基本步骤
通常在创建组件构造器时,传入template代表我们自定义组件的模板。 该模板就是在使用到组件的地方,要显示的HTML代码。
2.Vue.component(): 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。 所以需要传递两个参数:1、注册组件的标签名 2、组件构造器
3.组件必须挂载在某个Vue实例下,否则它不会生效。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue组件化基本使用</title>
</head>
<body>
<!--3.使用组件-->
<div id="app">
<cpn></cpn>
<cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
//ES6
//1.创建组件构造器对象
const cpnC = Vue.extend({
template: `
<div>
<h2>我是标题</h2>
<p>我是内容1</p>
<p>我是内容2</p>
</div>
`
})
//2.注册组件
// Vue.component('组件标签名','创建的组件名字')
Vue.component('cpn', cpnC)
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
}
})
</script>
</body>
</html>
1.3.3 父组件和子组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父组件与子组件</title>
</head>
<body>
<div id="app">
<cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.创建第一个组件(子组件)
const cpnC1 = Vue.extend({
template: `
<div>
<h2>我是标题啊1</h2>
<p>我是内容!!!!</p>
</div>`
})
// 2.创建第二个组件(父组件)
const cpnC2 = Vue.extend({
template: `
<div>
<h2>我是标题啊2</h2>
<p>我是内容!!!!2222</p>
<cpn1></cpn1>
</div>`,
components:{
cpn1:cpnC1
}
})
//root组件
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
components:{
cpn2:cpnC2
}
})
</script>
</body>
</html>
1.3.4 组件的语法糖和模板分离
1.全局组件注册的语法糖Vue.component('组件签名',{组件内容})2.局部组件注册的语法糖component:{'组件签名',{组件内容}}
模板分离两种方法:
1.使用scrpit,类型text/x-template标签
2.使用template标签
1.3.5 组件数据的存放
组件不能直接访问Vue实例的数据(data)使用方法:在组件注册时定义数据,并有返回值
Vue.component('cpn', {
template: '#cpn',
data(){
return {
title:'hahhahahahhhh'
}
}
})
1.3.6 父子组件的通信
1.3.6.1 父向子传数据(props)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父组件向子组件传递数据</title>
</head>
<body>
<div id="app">
<!-- 注意:要使用v-bind绑定数据-->
<cpn :vmovies="movies" :cm="message"></cpn>
</div>
<template id="cpn">
<div>
<ul>
<li v-for="item in vmovies"></li>
</ul>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 父传子,props
const cpn = {
template: '#cpn',
// 通过数组
// props: ['vmovies', 'cm'],
// 通过对象
props: {
// 1.类型限制
// vmoives: Array,
// cm:String
// 2.提供一些默认值,required设置必传值
cm:{
type:String,
default:'aaaaaaaaa',
required:true
},
// 类型是对象或者数组时,默认值是一个函数
vmovies:{
type:Array,
default(){
return []
}
}
},
data() {
return {}
},
methods: {}
}
const app = new Vue({
el: '#app',
// 父组件的数据
data: {
message: '你好啊',
movies: ['海王', '海贼王', '海绵宝宝']
},
components: {
// 增强写法,本是'cpn':cpn
cpn
}
})
</script>
</body>
</html>
1.3.6.2 子向父传数据($emit()发射事件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子传父</title>
</head>
<body>
<!--父组件模板-->
<div id="app">
<!-- 监听子组件发送的事件-->
<cpn @itemclick="cpnClick"></cpn>
</div>
<!--子组件模板-->
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)"></button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//子组件
const cpn = {
template: '#cpn',
data() {
return {
categories: [
{id: 'aaa', name: '热门推荐'},
{id: 'bbb', name: '手机数码'},
{id: 'ccc', name: '家用电器'},
{id: 'ddd', name: '电脑办公'},
]
}
},
methods: {
btnClick(item) {
// 发射事件,'事件名称',值
this.$emit('itemclick', item)
}
}
}
//父组件
const app = new Vue({
el: '#app',
// 父组件的数据
data: {
message: '你好啊',
movies: ['海王', '海贼王', '海绵宝宝']
},
components: {
// 增强写法,本是'cpn':cpn
cpn
},
methods: {
cpnClick(item) {
console.log(item)
}
}
})
</script>
</body>
</html>
1.3.6.3 父子间相互传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父子组件通信</title>
</head>
<body>
<div id="app">
<cpn :number1="num1"
:number2="num2"
@num1change="num1change"
@num2change="num2change"></cpn>
</div>
<template id="cpn">
<div>
<h2>props:</h2>
<h2>data:</h2>
<!-- <input type="text" v-model="dnumber1">-->
<input type="text" :value="dnumber1" @input="num1Input">
<h2>props:</h2>
<h2>data:</h2>
<!-- <input type="text" v-model="dnumber2">-->
<input type="text" :value="dnumber2" @input="num2Input">
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
num1: 1,
num2: 0
},
methods: {
num1change(value) {
this.num1 = parseFloat(value)
},
num2change(value) {
this.num2 = parseFloat(value)
}
},
components: {
cpn: {
template: '#cpn',
props: {
number1: Number,
number2: Number
},
data() {
return {
dnumber1: this.number1,
dnumber2: this.number2
}
},
methods: {
num1Input(event) {
// 1.将input中的value复制到dnumber
this.dnumber1 = event.target.value;
// 2.为了让父组件可以修改值,发出一个事件
this.$emit('num1change', this.dnumber1)
// 3.同时修饰dnumber2的值
this.dnumber2 = this.dnumber1 * 100;
this.$emit('num2change',this.dnumber2)
},
num2Input(event) {
this.dnumber2 = event.target.value
this.$emit('num2change', this.dnumber2)
this.dnumber1 = this.dnumber2 / 100;
this.$emit('num1change',this.dnumber1)
}
}
}
}
})
</script>
</body>
</html>
1.3.7 父子组件的访问方式
有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问跟组件。
1.3.7.1 父组件访问子组件 $children和$refs(推荐)的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父访问子-children-refs</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn ref="aaa"></cpn>
<button @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
methods: {
btnClick() {
// 1.$children
// console.log(this.$children);
// this.$children[0].showMessage()
// console.log(this.$children[0].name);
// 2.$refs(推荐)->对象类型,默认是空对象,设置ref
console.log(this.$refs.aaa.name);
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
name: '我是子组件的name'
}
},
methods: {
showMessage() {
console.log('showMessage')
}
}
}
}
})
</script>
</body>
</html>
1.3.7.2 子组件访问父组件 $parent和$root的使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件访问-子组件访问父组件</title>
</head>
<body>
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
我是cpn组件
<ccpn></ccpn>
</div>
</template>
<template id="ccpn">
<div>
<h2>我是子组件</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
components: {
cpn: {
template: '#cpn',
components: {
ccpn: {
template: '#ccpn',
methods: {
btnClick() {
//1.访问父组件$parent
console.log(this.$parent)
console.log(this.$parent.name)
//2.访问root组件
console.log(this.$root)
console.log(this.$root.message)
}
}
}
}
},
},
})
</script>
</body>
</html>
1.3.8 插槽slot
多处使用一个模板,但功能不同,可以使用插槽定义(占位),后在具体应用中设置不同的功能
插槽中可以定义默认值,之后使用重新定义可替换默认的功能
具名插槽:给插槽定义name,使用是在标签内说明slot='name名字',可以分辨不同的slot
作用域插槽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>作用域插槽</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn>
<!--目的:获取子组件的pLanguage-->
<template slot-scope="slot">
<!--<span v-for="item in slot.data"> - </span>-->
<!--使用join连接字符串-->
<span>slot.data.join(' - ')</span>
</template>
</cpn>
<cpn>
<!-- 目的:得到子组件的pLanguage-->
<template slot-scope="slot">
<span v-for="item in slot.data"> --=</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<!--data可改为自定义名字,获取组件中pLanguage数据-->
<slot :data="pLanguage">
<ul>
<li v-for="item in pLanguage"></li>
</ul>
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
//const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
components: {
cpn: {
template: '#cpn',
data() {
return {
pLanguage: ['JavaScrpit', 'C++', 'Python', 'C#', 'Go']
}
}
}
}
})
</script>
</body>
</html>
1.3.9 模块化开发
常见的模块化规范:CommonJS,AMD,CMD,ES6的Modules
1.3.10 Webpack
webpack是一个现代的JavaScript应用的静态模块打包工具。
插件:对某个现有的框架进行扩展
1.4 Vue cli(脚手架)
使用vue init webpack my-project(vue cli2)或者vue create my-project (vue cli3)初始化项目Vue cli2
Vue cli34>
Runtime-Compiler和Runtime-only的区别
两者在main.js中不同
runtimecompiler:
template->ast->render->vdom->UI
runtimeonly:(性能更高,代码量更少)
render->vdom->UI
1.5 vue-router(路由)
后端路由:后端处理URL和页面之间的映射关系
前后端分离:有ajax,前端url发送到静态资源服务器
前端路由:前端管理映射关系,抽取一部分js代码处理
1.5.1 改变URL,但是页面不进行整体的刷新的实现
1.5.2 动态路由:
1.5.3 路由懒加载
懒加载:需要用到时才进行加载
路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问到的时候, 才加载对应的组件
出去三个对应的js文件,有几个组件就打包成对应的js代码块
1.5.4 $route和$router的区别
$router为VueRouter实例,想要导航到不同URL,则使用$router.push方法 $route为当前router跳转对象里面可以获取name、path、query、params等1.5.5 导航守卫
vue-router提供的导航守卫主要用来监听监听路由的进入和离开的. vue-router提供了beforeEach和afterEach的钩子函数, 它们会在路由即将改变前和改变后触发.1.5.6 keep-alive
是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。属性:
1.6 Promise
1.6.1 什么情况会用到promise?
一般情况下是有异步操作时,使用promise对这个异步操作进行封装// 什么情况会用到promise?
// 一般情况下是有异步操作时,使用promise对这个异步操作进行封装
// new->执行构造函数(1 保存了一些状态信息 2.执行传入函数)
// 在执行传入的回调函数时,会传入两个参数,resolve,reject本身也是函数
new Promise((resolve, reject) => {
setTimeout(() => {
// 成功时调用resolve
// resolve('Hello world')
// 失败时调用reject
reject('error message')
}, 1000)
}).then((data) => {
console.log(data);
console.log(data);
console.log(data);
console.log(data);
}).catch((err) => {
console.log(err);
})
1.6.2 promise的三种状态
最简化代码
// 最简化
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
// 自己处理10行代码
console.log(res, '第一层代码');
// 2.对结果处理
return res + '111'
}).then(res => {
console.log(res, '第二层');
return Promise.reject('error message')
}).then(res => {
console.log(res, '第三层代码');
})
1.7 Vuex
vuex是一个专门为vue.js应用程序开发的状态管理模式
1.7.1 管理什么状态?
1.7.2 Vuex几个核心的概念
1.7.2.1 State单一状态树
单一数据源,管理应用层的全部状态,让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。1.7.2.2 Getters
类似于计算属性index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
counter: 1000,
students: [
{id: 110, name: 'why', age: 23},
{id: 112, name: 'Mois', age: 20},
{id: 113, name: 'dimmo', age: 10},
{id: 114, name: 'Molly', age: 19}
]
},
getters: {
powerCounter(state) {
return state.counter * state.counter
},
more20stu(state) {
return state.students.filter(s => s.age > 10)
},
more20stuLength(state, getters) {
return getters.more20stu.length
},
moreAgestu(state) {
return function (age) {
return state.students.filter(s => s.age > age)
}
}
},
modules: {}
})
export default store
App.vue
<template>
<div id="app">
<h2>---------App内容:getters相关信息-------------</h2>
<h2>$store.getters.powerCounter</h2>
<h2>$store.getters.more20stu</h2>
<h2>$store.getters.more20stuLength</h2>
<h2>$store.getters.moreAgestu(9)</h2>
<!-- <h2>$store.getters.more20stu.length</h2>-->
<h2>---------HelloVuex内容-------------</h2>
<hello-vuex/>
</div>
</template>
<script>
import HelloVuex from "./components/HelloVuex";
export default {
name: 'App',
components:{
HelloVuex
},
data() {
return {
message: '我是app组件',
counter:0
}
}
}
</script>
1.7.2.3 Mutation
Vuex的store状态的更新唯一方式:提交Mutation
Mutation主要包括两部分:
Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.
这就要求我们必须遵守一些Vuex对应的规则:方式二: 用心对象给旧对象重新赋值
删除使用Vue.delete index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
counter: 1000,
students: [
{id: 110, name: 'why', age: 23},
{id: 112, name: 'Mois', age: 20},
{id: 113, name: 'dimmo', age: 10},
{id: 114, name: 'Molly', age: 19}
]
},
// 同步操作
mutations: {
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
},
incrementCount(state, payload) {
// state.counter += payload
console.log("payloas",payload);
console.log("count:",payload.count);
state.counter += payload.count
},
addStudent(state,stu){
state.students.push(stu)
}
}
},
modules: {}
})
export default store
app.vue
<template>
<div id="app">
<h2>---------App内容-------------</h2>
<h2></h2>
<button @click="addition">+</button>
<button @click="subtraction">-</button>
<button @click="addCount(5)">+5</button>
<button @click="addCount(10)">+10</button>
<button @click="addStudent">添加学生</button>
<!-- <h2></h2>-->
<h2>---------HelloVuex内容-------------</h2>
<hello-vuex/>
</div>
</template>
<script>
import HelloVuex from "./components/HelloVuex";
export default {
name: 'App',
components:{
HelloVuex
},
data() {
return {
message: '我是app组件',
counter:0
}
},
methods:{
addition(){
// 括号内为方法名
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
addCount(count){
// 1、普通提交风格
// this.$store.commit('incrementCount',count)
// 2.特殊的提交封装
this.$store.commit({
type:'incrementCount',
count
})
},
addStudent(){
const stu ={id:114,name:'alan',age:33}
this.$store.commit('addStudent',stu)
}
}
}
</script>
1.7.2.4 Action
Action类似于Mutation, 但是是用来代替Mutation进行异步操作的. 调用action方法时要用dispatchmutations: {
updateName(state,payload){
state.name=payload
}
},
// 异步操作
actions: {
aUpdateName(context){
setTimeout(()=>{
context.commit('updateName','xixiximois')
},1000)
}
}
//调用
updateName(){
this.$store.commit('updateName','hahamois')
},
1.7.2.5 Module
声明一个模块,局部通过context.state暴露,根结点状态为context.rootStateconst moduleA={
state: {
name:'MMMois'
},
// 同步操作
mutations: {
updateName(state,payload){
state.name=payload
}
},
// 异步操作
actions: {
aUpdateName(context){
setTimeout(()=>{
context.commit('updateName','xixiximois')
},1000)
}
},
// 类似计算属性
getters: {
fullname(state){
return state.name+'222222'
},
fullname2(state,getters){
return getters.fullname+'333333333'
},
// 拼接主模块的内容rootState
fullname3(state,getters,rootState){
return getters.fullname+'333333333'+rootState.counter
}
},
}