let/var
let为作用域严格的var
ES5之前因为if和for都没有块级作用域的概念,所以在很多时候,都必须借助于function的作用域来解决应用外面变量的问题(闭包)
const
定义常量,在定义时就必须赋值,若常量指向的是对象,则可以对对象的内部属性进行修改
对象属性简写
let name = 'xiaoming'
// ES6之前
let obj1 = {
name: name
}
// ES6之后
let obj2 = {
name
}
对象方法简写
// ES6之前
let obj1 = {
test: function () {}
}
// ES6之后
let obj2 = {
test () {}
}
for (let i = 0; i < arrs.length; i++) {
console.log(arrs[i]);
}
for (let i in arrs) {
console.log(arrs[i]);
}
for (let arr of arrs) {
console.log(arr)
}
+
连接\
没有参数
const a = () => {
}
一个参数,可以省略参数的括号
const b = num => {
return num * num
}
多个参数
const c = (num1, num2) => {
return num1 + num2
}
方法体只有一行代码
const d = (num1, num2) => num1 * num2
异步编程的一种解决方案
resolve
时,就处于该状态,并且会回调.then()
reject
时,就处于该状态,并且会回调.catch()
示例
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello World')
reject('error message')
}, 1000)
}).then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
Promise.resolve()
:将数据包装成Promise对象,并且在内部回调resolve()
函数Promise.reject()
:将数据包装成Promise对象,并且在内部回调reject()
函数参数中所有的Promise完成后执行
Promise.all([
new Promise(……)
]).then(results => {
})
const obj = {
name: 'xiaoming',
age: 18,
sex: 'nan'
}
const {name, age} = obj;
const names = ['zhangsan', 'lisi']
const [name1, name2] = names;
过滤数组中满足条件的元素返回成新数组
let newNums = nums.filter(function (n) {
return n < 100;
});
filter中的回调函数必须返回一个Boolean值
依次对数组所有元素进行操作返回操作后的数组
let newNums = nums.map(function (n) {
return n * 2;
});
对数组中所有的内容进行汇总
let total = newNums.reduce(function (preValue, n) {
return preValue + n;
}, 0);
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
参数说明
function(total,currentValue, index,arr)
:必需。用于执行每个数组元素的函数。
total
:必需。初始值, 或者计算结束后的返回值。currentValue
:必需。当前元素currentIndex
:可选。当前元素的索引arr
:可选。当前元素所属的数组对象。initialValue
:可选。传递给函数的初始值官方文档https://cn.vuejs.org/v2/guide
v-once
:该指令后面不需要跟任何表达式,只渲染一次v-html
:以html格式渲染数据v-text
:以文本格式渲染数据v-pre
:不进行解析渲染,直接显示标签内文本v-cloak
:给标签设定这个属性后css设置[v-cloak]{display:none;}
,可以防止渲染过慢导致用户看到原本的内容。原理:当解析完成后,会去掉这个属性动态绑定属性,缩写 :
,例子: v-bind:属性名="变量名"
v-bind
动态绑定class
v-bind:class="{‘active‘: isActive, ‘line‘: isLine}"
class="title" v-bind:class="{‘active‘: isActive, ‘line‘: isLine}"
class="title" v-bind:class="classes"
v-bind:class="[‘active‘, ‘line‘]"
class="title" v-bind:class="[‘active‘, ‘line‘}"
class="title" v-bind:class="classes"
v-bind
动态绑定style
v-bind:style="{color: currentColor, fontSize: fontSize + ‘px‘}"
v-bind:style="[baseStyles, overridingStyles]"
基本使用
data: {firstName: '', lastName: ''},
computed: {
fullName: function () {
return this.firstName + '' + this.lastName
}
}
完整写法(本质)
data: {firstName: '', lastName: ''},
computed: {
fullName: {
set: function(newValue) {
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[1];
},
get: function () {
return this.firstName + '' + this.lastName
}
}
}
computed比methods好的地方:有缓存,调用多次只会计算一次
绑定事件监听器,缩写:@
,例子: v-on:"xxx"
参数问题
event
参数传递进去event
时,可以通过$event
传入事件修饰符
.stop
:调用event.stopPropagation()
——停止冒泡(嵌套的外层标签的事件不触发).prevent
:调用event.preventDefault()
——阻止默认事件(阻止表单提交).{keyCode|keyAlias}
:只当事件是从特定键触发时才触发回调.native
:监听组件根元素的原生事件.once
:只触发一次回调<p v-if="score>=90">优秀</p>
<p v-else-if="score>=80">良好</p>
<p v-else-if="score>=60">及格</p>
<p v-else>不及格</p>
输入框时虚拟DOM导致的复用问题,标签加上key属性,赋值不一样则不会复用
v-if
指令的元素,根本就不会存在DOM中v-show
只是给我们的元素添加一个行内样式:display: none
;v-for="item in items"
v-for="(item, index) in items"
v-for="item in info"
v-for="(value, key) in info"
v-for="(value, key, index) in info"
注意点:组件的key属性,在使用v-for
时,给对应的元素或者组件添加上一个:key
属性,可以高效的更新虚拟DOM,要注意:key
值的唯一性
定义:
filters: {
showPrice(price) {
return '¥' + price.toFixed(2)
}
}
使用:{{变量名 | 过滤器方法名}}
响应式的数组的方法
.push()
:在数组最后面添加元素.pop()
:删除数组中的最后一个元素.shift()
:删除数组中的第一个元素.unshift()
:在数组最前面添加元素.splice()
:三个参数,从参数一开始,删除长度为参数二的元素,添加参数二后面的所有参数.sort()
:排序.reverse()
:反转Vue.set(要修改的对象,索引值,修改后的值)
:修改直接通过索引修改元素不是响应式的
v-bind
绑定一个value
属性v-on
指令给当前元素绑定input
事件下面两行代码等效
<input type="text" v-model="message">
<input type="text" v-bind:value="message" v-on:input="message = $event.target.value">
.lazy
:默认是同步更新,lazy修饰符可以让数据在失去焦点或者回车时才会更新.number
:输入框默认会将输入内容当作字符串,number修饰符可以让输入框输入的内容自动转成数字类型.trim
:去掉左右两边的空格组件的使用分成三个步骤
Vue.extend()
方法Vue.component()
方法基本示例
<div id="app">
<!-- 3.使用组件 -->
<my-cpn></my-cpn>
</div>
<script>
//1.创建组件构造器对象
const cpnC = Vue.extend({
template: `
<div>
<h1>我是标题</h1>
</div>
`
})
//2.注册组件
Vue.component('my-cpn', cpnC)
</script>
<script>
const cpnC = Vue.extend({
template: `
<div>
<h1>我是标题</h1>
</div>
`
})
//全局组件,可以在多个Vue的实例下使用
Vue.component('cpn1', cpnC)
const app = new Vue({
el: '#app',
components: {
//局部组件,只能在当前Vue实例下使用
//cpn2代表使用组件的标签名
//cpnC代表组件名
cpn2: cpnC
}
})
</script>
<script>
//组件1(子组件)
const cpnC1 = Vue.extend({
template: `
<div>
<h1>我是标题</h1>
</div>
`
})
//组件2,在组件2中注册组件1(父组件)
const cpnC2 = Vue.extend({
template: `
<div>
<h1>我是标题</h1>
</div>
`,
components: {
cpn1: cpnC1
}
})
const app = new Vue({
el: '#app',
components: {
cpn2: cpnC2
}
})
</script>
子组件只能在父组件中使用,不能在父组件的父组件中使用
省去了调用Vue.extend()的步骤,而是可以直接使用一个对象来代替
<script>
//注册全局组件
Vue.component('cpn1', {
template: `
<div>
<h1>我是标题</h1>
</div>
`
})
const app = new Vue({
el: '#app',
components: {
//注册局部组件
cpn2: {
template: `
<div>
<h1>我是标题</h1>
</div>
`
}
}
})
</script>
<script type="text/x-template" id="cpn">
<div>
<h1>我是标题</h1>
</div>
</script>
<script>
Vue.component('cpn', {
template: '#cpn'
})
</script>
<template id="cpn">
<div>
<h1>我是标题</h1>
</div>
</template>
<script>
Vue.component('cpn', {
template: '#cpn'
})
</script>
data不能写成属性,要写成函数返回值
<script>
Vue.component('cpn', {
template: '#cpn',
data() {
return {
……
}
}
})
</script>
props
向子组件传递数据在子组件中添加props
选项
props: ['变量1', '变量2']
同时可以进行数据验证
Vue.component('cpn', {
props: {
//基础的类型检查('null'匹配任何类型)
propA: Number,
//多个可能的类型
propB: [String, Number],
//必填的字符串
propC: {
type: String,
required: true
},
//带有默认值的数字
propD: {
type: Number,
default: 100
},
//带有默认值的对象
propE: {
type: Object,
default: function () {
return {message: 'hello'}
}
},
//自定义验证函数
propF: {
validator: function (value) {
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
通过v-bind绑定父组件中的变量
当变量名是驼峰命名时,v-bind:cInfo="info"
需要写成 v-bind:c-info="info"
自定义事件的流程
$emit()
来触发事件代码演示
<!-- 父组件模板 -->
<div id="app">
<!-- 3.监听自定义事件meth的触发,调用父组件中的方法cpnClick,不传参数原生事件默认传event,自定义事件会将参数自动传过去 -->
<cpn @meth="cpnClick"></cpn>
</div>
<!-- 子组件模板 -->
<template id="cpn">
<!-- 1.调用子组件中的方法 -->
<button @click="btnClick(para)"></button>
</template>
<script>
//子组件
const cpn = {
template: '#cpn',
methods: {
btnClick(para) {
//2.发射事件,自定义meth事件
this.$emit('meth', para)
}
}
}
//父组件
const app = new Vue({
el: '#app',
components: {
cpn
},
methods: {
//4.接收数据,处理事件
cpnClick(para) {
console.log(para)
}
}
})
</script>
$children
或$refs
$parent
this.$children
是一个数组类型,包含所有子组件对象
给子组件的标签中添加 ref="xxx"
属性,this.$refs
是一个数组类型,this.$refs.xxx
是具体某个子组件
$parent
:访问父组件$root
:访问根组件<slot></slot>
<slot>button</slot>
给每个插槽name
属性,替换插槽时增加一个slot="name"
属性
<div id="app">
<cpn><span slot="center">标题</span></cpn>
</div>
<template id="cpn">
<div>
<slot name="left"><span>左边</span></slot>
<slot name="center"><span>中间</span></slot>
<slot name="right"><span>右边</span></slot>
</div>
</template>
父组件替换插槽的标签,但是数据由子组件提供
<div id="app">
<cpn>
<template slot-scope="slot">
<span v-for="item in slot.abc">{{item}}</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :abc="arrs">
<span v-for="item in arrs">{{item}}</span>
</slot>
</div>
</template>
module.exports = {
变量名, 函数名
}
const {变量名, 函数名} = required('./xxx.js')
引入js文件时,类型需设置为module
<script src="xxx.js" type="module"></script>
导入时名称需与导出文件里一致
export 变量名, 函数名
default导出,导入时可以自定义命名,每个模块只能有一个default导出
export default 变量名, 函数名
//导入指定信息
import {变量名, 函数名} from "./xxx.js"
//导入时自定义名称
import 自定义变量名 from "./xxx.js"
//导入所有信息
import * as info from "./xxx.js"
从本质上来讲,webpack是一个现代的JavaScript应用的静态模块打包工具
node -v
npm install webpack@3.6.0 -g
--save-dev
是开发时依赖,项目打包后不需要继续使用的:npm install webpack@3.6.0 --save-dev
- dist:用于存放之后打包的文件
- src:用于存放我们写的源文件
- main.js:一个js入口文件
- index.html:浏览器打开展示的首页html
- package.json:通过npm init生成的,npm包管理的文件
打包指令:webpack src/main.js dist/bundle.js
配置打包的文件和输出文件的简单指令
npm init
:初始化node环境,会在根目录生成package.json
文件npm install
:根据package.json
文件中的依赖安装相关内容
根目录下新建webpack.config.js
文件
const path = require('path')
module.exports = {
//需要进行打包的js入口文件
entry: './src/main.js',
output: {
//动态获取输出文件目录绝对路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
}
配置好后直接执行webpack
指令就能进行打包
(可选)安装局部webpack:npm install webpack@3.6.0 --save-dev
编辑package.json
文件
……
"scripts": {
……
"build": "webpack"
}
……
webpack
命令映射成npm run build
webpack
时会使用全局的webpack,而使用映射的命令会优先使用局部的webpack打包时用来转化js以外的文件
文档https://www.webpackjs.com/loaders
使用步骤
在js入口文件中依赖css文件:require(‘./css/normal.css‘)
css-loader
和style-loader
css-loader
负责将css文件进行加载style-loader
负责将样式添加到DOM中use
的顺序是从右往左:[‘style-loader‘, ‘css-loader‘]
使用url-loader
配置
file-loader
,会将文件复制到dist
文件夹下并哈希值重命名图片命名配置,在options中添加如下选项
img
:文件要打包到的文件夹name
:获取图片原来的名字,放在该位置hash:8
:为了防止图片名称冲突,依然使用hash,但是只保留8位ext
:使用图片原来的扩展名图片路径问题
webpack
会将生成的路径直接返回给使用者dist
文件夹下的,所以需要在路径下再添加一个dist/
,配置publicPath: "dist/"
配置
use: [
{
loader: 'url-loader',
options: {
limit: 8196,
name: 'img/[name].[hash:8].[ext]'
},
}
]
在webpack中,使用babel将ES6语法转成ES5
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
配置webpack.config.js文件
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
npm安装
npm install --save vue
在js中导入Vue并使用
import Vue from 'vue'
重新打包,运行程序
默认导入的是runtime-only
,其中没有编译template的东西,需要导入runtime-compiler
修改webpack的配置文件webpack.config.js
module.exports = {
……
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
}
安装vue-loader和vue-template-compiler
npm install vue-loader vue-template-compiler --save-dev
修改webpack.config.js的配置文件
{
test: /\.vue$/,
use: ['vue-loader']
}
注意:vue14版本以上需要一个插件,或者降版本13.0.0
自动生成一个index.html文件(可以指定模板来生成)并将打包的js文件,自动通过script标签插入到body中
安装 npm install html-webpack-plugin --save-dev
使用,修改webpack.config.js文件中的plugins部分
const HtmlWebpackPlugin = require('html-webpack-plugin')
……
plugins: [
new HtmlWebpackPlugin({
template: 'index.html'
}),
]
安装 npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
修改webpack.config.js文件,使用插件
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
……
plugins: [
new UglifyjsWebpackPlugin()
]
基于node.js搭建,内部使用express框架,可以实现浏览器自动刷新显示修改后的结果
安装 `npm install --save-dev webpack-dev-server@2.9.1
devserver是webpack的一个选项,有如下属性可以配置./dist
webpack.config.js文件配置修改
derServer: {
contentBase: './dist',
inline: true
},
配置scripts,使用安装了本地服务器的局部webpack
"dev": "webpack-dev-server --open"
--open
参数表示直接打开浏览器
直接运行npm run dev
即可
官方网站 https://cli.vuejs.org/zh/
安装NodeJS
检测安装的版本
默认情况下自动安装Node和NPM
node -v
npm -v
淘宝npm镜像cnpm安装
npm install -g cnpm --registry=https://registry.npm.taobao.org
然后使用cnpm命令来安装模块
cnpm install [name]
Webpack的全局安装
npm install webpack -g
安装Vue脚手架
npm install -g @vue/cli
查看版本 vue --version
安装的是Vue CLI3的版本,如果要按照Vue CLI2的方式初始化项目是不可以的,这时需要拉取2.x的模板
npm install @vue/cli-init -g
初始化项目
vue init webpack my-project
vue create my-project
修改配置:webpack.base.conf.js起别名
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'pages': resolve('src/pages'),
'common': resolve('src/common'),
'components': resolve('src/components'),
'network': resolve('src/network')
}
}
在根目录下新建配置文件vue.config.js
module.exports = {
……
}
官方文档https://router.vuejs.org/zh/
npm install vue-router --save
vue-router
是一个插件,通过Vue.use()
来安装)
导入路由对象,并且调用`Vue.use(VueRouter)(router/index.js)
import VueRouter from 'vue-router'
import Vue from 'vue'
Vue.use(VueRouter)
创建路由实例,并且传入路由映射配置(./router/index.js)
const routes = [
]
const router = new VueRouter({
routes
})
export default router
在Vue实例中挂载创建的路由实例(./main.js)
//导入的位置是一个目录时自动寻找index文件,可以省略不写
import router from './router'
new Vue({
……
router,
})
配置路由映射:组件和路径映射关系(./router/index.js)
import Home from '../components/Home'
const routes = [
{
path: '/home',
component: Home
},
]
使用路由:通过<router-link>
和<router-view>
<router-link to="/home">首页</router-link>
<!-- <router-view>决定渲染位置 -->
<router-view></router-view>
<router-link>
会被渲染成一个<a>
标签<router-view>
会根据当前的路径,动态渲染处不同的组件<router-view>
挂载的组件,其他内容不会发生改变重定向配置默认路径
const routes = [
{
path: '',
redirect: '/home'
},
{
path: '/home',
component: Home
},
]
改变路由模式hash为history(改变后路径上不会有#)
const router = new VueRouter({
routes,
mode: 'history'
})
<router-link to=‘/home‘ tag=‘li‘>
会被渲染成一个<li>
元素<router-link>
对应的路由匹配成功时,会自动给当前元素设置一个router-link-active
的class,在./router/index.js
中设置linkActiveClass
可以修改默认的名称通过js代码来跳转,template部分
<button @click="linkToHome">首页</button>
script部分
export default {
name: 'App',
methods: {
linkToHome() {
this.$router.push('/home')//可以使用返回
this.$router.replace('/home')//不能使用返回
}
}
}
路径映射配置
path: '/user/:id',
component: User
组件模板
<router-link :to="'/user/' + id">用户</router-link>
目标组件获取动态传入的参数
computed: {
userId() {
return this.$route.params.id
}
}
const routes = [
{
path: '/home',
component: () => import('../components/Home')
},
]
<router-view>
标签实现
const routes = [
{
path: '/home',
component: Home,
children: [
{
path: 'message',
component: Message
},
]
},
]
/router/:id
/router/123, /router/abc
/router
,也就是普通配置/router?id=123, /router?id=abc
组件模板部分
<router-link :to="{path: '/profile', query: {name: 'xiaoming', age: 18}}>档案</router-link>
目标组件获取query对象
$route.query
通过$route
对象获取,在使用vue-router
的应用中,路由对象会被注入每个组件中,赋值为this.$route
,并且当路由切换时,路由对象会被更新
$route
和$router
的区别$router
为VueRouter
实例,想要导航到不同URL,则使用$router.push
方法$route
为当前router
跳转对象,里面可以获取name
、path
、query
、params
等类似Spring的拦截器
官方文档https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
Vue.js devtools
npm install vuex --save
创建入口文件./store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
//1.安装插件
Vue.use(Vuex)
//2.创建对象
const store = new Vuex.Store({
state: {
//共享的状态变量
},
mutations: {
//修改状态
},
actions: {
//异步修改状态
},
getters: {
//状态的“计算属性”
},
modules: {
}
})
//3.导出store对象
export default store
挂载
import store from './store'
new Vue({
el: '#app',
store,
reder: h => h(App)
})
使用,通过$store.state
取出共享的状态变量
this.$store.state.属性
的方式来访问状态this.$store.commit(‘mutation中方法‘)
来修改状态store.state.count
,因为Vuex可以更明确地追踪状态的变化,所以不要直接改变store.state.count
的值./store/index.js
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
},
decrement(state) {
state.count--
}
},
actions: {
},
getters: {
},
modules: {
}
})
组件中
<button @click="add">+1</button>
<button @click="sub">-1</button>
……
computed: {
count: function() {
return this.$store.state.count
}
},
methods: {
add: function() {
this.$store.commit('increment')
},
sub: function() {
this.$store.commit('decrement')
}
}
this.$store.commit({
type: 'changeCount',
count: 100
})
count变成一个对象的属性
changeCount(state, payload) {
state.count = payload.count
}
类似计算属性,获取一些state变化后的状态
getters作为参数
getters: {
greaterAgesStus: state => {
return state.students.filter(s => s.age >= 20)
},
greaterAgesCount: (state, getters) => {
return getters.greaterAgesStus.length
}
}
getters传递参数
getters: {
styById: state => {
return id => {
return state.students.find(s => s.id ===id)
}
}
}
npm install axios --save
import axios from ‘axios
使用(Promise方式)
axios({
url: xxx
//针对get请求的参数拼接
params: {
type: 'pop'
page: 1
}
}).then(res => {
//返回结果在res.data里
console.log(res)
})
axios.all
,可以放入多个请求的数组axios.all([])
返回的结果是一个数组,使用axios.spread
可将数组[res1, res2]
展开为res1
, res2
代码示例
axios.all([
axios.get('url'),
axios.get('url',
{
params: {
type: 'sell'
}
})
]).then(axios.spread((res1, res2) => {
console.log(res1)
console.log(res2)
}))
代码示例
axios.defaults.baseURL = 'xxx'
axios({
url: '/home/data'
})
常见的配置选项
url: ‘/user‘
method: ‘get‘
baseURL: ‘http://www.mt.com/api‘
transformRequest: [function(data){}]
transformResponse: [function(data){}]
headers: {‘x-Requested-With‘: ‘XMLHttpRequest‘}
params: {id: 2}
paramsSerializer: function(params){}
data: {key: ‘aa‘}
timeout: 1000
withCredentials: false
adapter: function(resolve, reject, config){}
auth: {uname: ‘‘, pwd:‘‘}
responseType: ‘json‘
代码示例
const instance1 = axios.create({
baseURL: 'xxx'
})
instance1({
url: '/data'
}).then(res => {
console.log(res)
})
instance.interceptors.request.use(config => {
console.log('来到了request拦截success中');
return config
}, err => {
console.log('来到了request拦截failure中');
return err
})
instance.interceptors.response.use(response => {
console.log('来到了response拦截success中');
return response.data
}, err => {
console.log('来到了response拦截failure中');
return err
})
原文:https://www.cnblogs.com/yxmhl/p/11863479.html