双向绑定是一种数据绑定技术,它能够实现数据的自动同步更新,即当用户修改了数据时,界面也会随之自动更新,反之亦然。其原理如下:
数据模型:双向绑定的第一步是建立一个数据模型,它是绑定的核心。数据模型需要定义一个属性,这个属性的值会被绑定到视图层的控件上。
视图层:视图层是指用户界面,在这里指控件。控件需要绑定到数据模型的属性上,当数据模型的属性发生变化时,控件会自动更新。
绑定器:绑定器是双向绑定的桥梁。绑定器可以监听数据模型的属性变化,并将这些变化同步到视图层,同时,它也能监听控件的用户操作,将这些操作同步到数据模型。
数据流:数据流是指信息的传递方向。双向绑定的数据流是双向的,即数据可以从数据模型到视图层,也可以从视图层到数据模型。
综上所述,双向绑定的原理就是通过建立数据模型、视图层和绑定器之间的桥梁,实现数据的自动同步更新。这种技术可以大大简化开发工作,提高用户体验。
Vue是一种用于构建用户界面的渐进式框架,具有简单易用、高效灵活等特点。下面是基础创建项目的步骤:
npm install -g @vue/cli
vue create my-project
其中 my-project 是你要创建的项目名称,可以根据需要进行更改。
4. 选择项目配置:执行以上命令后,会让你选择预设的配置项或者手动配置,根据需要进行选择。
5. 安装项目依赖:创建完项目后,需要安装项目所需的依赖,可以在命令行中进入到项目根目录,输入以下指令安装依赖:
cd my-project
npm install
npm run serve
Vuex是一个专门为Vue.js设计的状态管理库,它可以帮助我们在Vue.js应用程序中管理应用程序的状态。Vuex的核心概念包括state、mutation、action、getter和module。
state:存储应用程序的状态,可以通过$store.state访问。
mutation:用于修改state中的数据,可以通过commit提交一个mutation实现。
action:用于异步操作或者批量提交mutation,可以通过dispatch提交一个action实现。
getter:用于获取state中的数据,可以通过$store.getters访问。
module:用于将store拆分成多个模块,每个模块管理自己的状态、mutation、action和getter。
下面是一个简单的Vuex实例,用于管理一个购物车应用程序的状态:
// 定义state
const state = {
items: []
}
// 定义mutation
const mutations = {
addItem(state, item) {
state.items.push(item)
},
removeItem(state, index) {
state.items.splice(index, 1)
}
}
// 定义action
const actions = {
addItem({commit}, item) {
setTimeout(() => {
commit('addItem', item)
}, 1000)
},
removeItem({commit}, index) {
setTimeout(() => {
commit('removeItem', index)
}, 1000)
}
}
// 定义getter
const getters = {
count(state) {
return state.items.length
}
}
// 创建store
import Vuex from 'vuex'
const store = new Vuex.Store({
state,
mutations,
actions,
getters
})
// 在组件中使用
购物车中商品数量: {{ $store.getters.count }}
Vuex 是一个专门为 Vue.js 应用程序设计的状态管理库,它使得多个组件之间的状态共享变得更加容易和可维护。Vuex 中包含多个方法,下面是其中的一些方法及使用方式和示例:
state 是 Vuex 中的基本属性,它用于存储数据的状态。通过在组件中调用 state 来获取当前的状态。
示例代码:
const store = new Vuex.Store({
state: {
count: 0
}
})
// 获取 state 中的 count 值
store.state.count
getters 用于获取 store 中的数据,有点类似于组件中的计算属性。getters 可以接受 state 作为第一个参数,也可以接受其他的 getters 作为第二个参数。
示例代码:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'Todo 1', done: true },
{ id: 2, text: 'Todo 2', done: false }
]
},
getters: {
doneTodos(state) {
return state.todos.filter(todo => todo.done)
}
}
})
// 获取 getters 中的 doneTodos
store.getters.doneTodos
mutations 用于修改 state 中的数据,它必须是同步的函数。mutations 接受 state 作为第一个参数,第二个参数是需要修改的数据。
示例代码:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
},
decrement(state) {
state.count--
}
}
})
// 调用 mutations 中的 increment 方法
store.commit('increment')
actions 用于异步修改 state 中的数据,它可以包含任意异步操作。actions 接受一个 context 参数,可以通过 context.commit 方法来调用 mutations 中的方法。
示例代码:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
incrementAsync(context) {
setTimeout(() => {
context.commit('increment')
}, 1000)
}
}
})
// 调用 actions 中的 incrementAsync 方法
store.dispatch('incrementAsync')
modules 是 Vuex 中用于拆分 store 的方法,它允许我们将 store 拆分成多个模块,每个模块有自己的 state、mutations、actions 和 getters。每个模块中的 state、mutations、actions 和 getters 都可以像普通的 Vuex 实例一样调用。
示例代码:
const moduleA = {
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
getters: {
doubleCount(state) {
return state.count * 2
}
}
}
const moduleB = {
state: {
message: 'Hello World'
},
mutations: {
setMessage(state, payload) {
state.message = payload
}
},
actions: {
setMessageAsync(context, payload) {
setTimeout(() => {
context.commit('setMessage', payload)
}, 1000)
}
}
}
const store = new Vuex.Store({
modules: {
moduleA,
moduleB
}
})
// 获取 moduleA 中的 count
store.state.moduleA.count
// 调用 moduleA 中的 mutations 中的 increment 方法
store.commit('moduleA/increment')
// 获取 moduleA 中的 getters 中的 doubleCount
store.getters['moduleA/doubleCount']
// 调用 moduleB 中的 actions 中的 setMessageAsync 方法
store.dispatch('moduleB/setMessageAsync', 'Hello Vuex')
import axios from 'axios'
const store = new Vuex.Store({
state: {
data: null
},
mutations: {
setData(state, payload) {
state.data = payload.data
}
},
actions: {
fetchData({ commit }) {
axios.get('/api/data')
.then(response => {
commit('setData', { data: response.data })
})
.catch(error => {
console.log(error);
});
}
}
})
{{ data }}
解释:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。在该模式下,应用的每个组件都可以直接访问应用级别的状态。
在 Vuex store 中,我们定义了三个部分:state,mutations,actions。
state:用于存储应用级别的状态,可以在组件中通过 $store.state 访问。
mutations:用于修改 state 中的数据,只能通过调用 mutations 中的方法来修改 state 中的数据,也就是说,不能直接修改 state 中的数据。
actions:用于调用接口,并提交 mutations 来修改 state 中的数据。
在组件中,我们通过 computed 计算属性来访问 state 中的数据,并在 created 钩子函数中调用 actions 中的方法来获取数据。
本地存储持久化是指将 Vuex 中的数据存储在浏览器本地,下次打开页面时可以直接从本地获取存储的数据。这样能够增加用户体验,同时也可以减轻服务器的负担。
在 Vue2 中使用 Vuex 实现本地存储持久化,可以通过 vuex-persistedstate 插件来实现。步骤如下:
npm install vuex-persistedstate --save
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import persistedState from 'vuex-persistedstate'
Vue.use(Vuex)
export default new Vuex.Store({
plugins: [
persistedState({
// 存储在本地的 key 值,默认为 vuex
key: 'myVuex',
// 存储方式,localStorage 或 sessionStorage,默认为 localStorage
storage: window.sessionStorage
})
],
state: {
// ...
},
mutations: {
// ...
},
actions: {
// ...
}
})
需要注意的是,在使用 vuex-persistedstate 插件时,需要注意数据的安全性,不能存储敏感信息。同时也需要及时清除不再需要的数据,否则会占用过多的本地存储空间。
另外还有另一种方式可以实现本地存储持久化,那就是使用 Vuex 的 subscribe 方法配合浏览器本地存储 API 完成。具体实现可以参考 Vue CLI 中使用 Vuex 持久化存储。
在 main.js 中,可以通过下面的代码全局引入 vant 组件:
import Vue from 'vue'
import Vant from 'vant'
import 'vant/lib/index.css'
Vue.use(Vant)
如果只需要在某些组件中使用 vant,可以在组件中按需引入。在组件的 script 标签中,导入需要使用的组件即可,例如:
<template>
<div>
<van-button type="primary">按钮</van-button>
</div>
</template>
<script>
import { Button } from 'vant';
export default {
components: {
[Button.name]: Button
}
}
</script>
在上面的例子中,我们只需要使用 Button 组件,因此只需要在 script 中导入 Button 组件,并在 components 中注册即可。
需要注意的是,在使用 Button 组件时,要使用 [Button.name]
来注册组件,否则 Vue 会提示组件未注册的错误。
在 main.js
中,可以通过下面的代码全局引入 Element 组件:
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
如果只需要在某些组件中使用 Element,可以按需引入。在组件的 script 标签中,导入需要使用的组件即可,例如:
<template>
<div>
<el-button type="primary">按钮</el-button>
</div>
</template>
<script>
import { Button } from 'element-ui';
export default {
components: {
'el-button': Button,
},
};
</script>
需要注意的是,在组件中引用 Element 组件时,要使用驼峰式命名来注册组件,如 el-button
组件。如果使用 Element 组件时出现未注册的错误,可以检查组件名是否正确注册。
首先我们需要安装 postcss-pxtorem
插件,该插件能够将我们编写的 px
值自动转换为 rem
。使用以下命令安装该插件:
npm install postcss-pxtorem --save-dev
在项目根目录新建 postcss.config.js
,然后配置如下:
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 16, // 设计稿宽度的 1/10,因为我们一般是基于750px的设计稿进行开发,所以这里设置为75
propList: ['*'], // 对所有属性进行转换
},
},
};
在项目根目录的 vue.config.js
中,添加以下内容:
module.exports = {
css: {
loaderOptions: {
postcss: {
plugins: [
require('postcss-pxtorem')({
rootValue: 16,
propList: ['*'],
}),
],
},
},
},
};
这一步是为了将 postcss-pxtorem
插件添加到 Vue 的构建中。
现在我们来验证一下是否配置成功。我们在某个组件中的样式中定义一个 font-size
属性:
.demo {
font-size: 32px;
}
保存后,如果你的开发环境是 VS Code 或者 WebStorm 等 JetBrains 系列的产品,可能会看到下面的警告:
Unknown property ‘font-size’. Declaration ignored.
此时重新启动一下 npm run serve
命令,应该就可以看到样式已经正常生效了,并且 font-size
的值已经自动转换为了 rem
。
在 Vue CLI 2.x 中,可以通过在项目根目录下创建 vue.config.js
文件来进行项目配置。
常见的一些配置项如下:
// vue.config.js
module.exports = {
configureWebpack: {
plugins: [
new MyAwesomeWebpackPlugin()
]
}
}
// vue.config.js
module.exports = {
devServer: {
proxy: 'http://localhost:3000'
}
}
// vue.config.js
module.exports = {
publicPath: process.env.NODE_ENV === 'production'
? '/production-sub-path/'
: '/'
}
// vue.config.js
module.exports = {
outputDir: 'dist',
assetsDir: 'static'
}
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
// 修改它的选项...
return options
})
}
}
需要注意的是,Vue CLI 2.x 的 vue.config.js
配置文件需要安装 vue-cli-plugin-
的插件来扩展,例如如下:
// vue.config.js
module.exports = {
pluginOptions: {
foo: {
// 插件配置
}
}
}
若是想使用这种方式扩展 vue-cli-service
的行为,可以通过 chainWebpack
或 configureWebpack
来实现。
详细的配置项可以参考 官方文档。
MD5、3DES、SHA1 都是常用的加密算法,下面分别介绍如何在 JavaScript 中使用这些算法进行加解密。
在 JavaScript 中使用 MD5 加密可以使用第三方库 js-md5
,使用非常简单。
首先安装该库:
npm install js-md5 --save
然后在代码中引入:
import md5 from 'js-md5'
// 对字符串 'hello' 进行 MD5 加密
const encrypted = md5('hello')
console.log(encrypted) // 输出 '5d41402abc4b2a76b9719d911017c592'
在 JavaScript 中使用 3DES 加解密需要依赖第三方库 crypto-js
。
先安装该库:
npm install crypto-js --save
接下来,我们来分别介绍 3DES 的加密和解密。
import CryptoJS from 'crypto-js'
// 定义密钥
const key = CryptoJS.enc.Utf8.parse('1234567890123456') // 16 字节的密钥
// 定义偏移量
const iv = CryptoJS.enc.Utf8.parse('12345678') // 8 字节的偏移量
// 待加密的数据
const data = 'hello world'
// 加密
const encrypted = CryptoJS.TripleDES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
// 输出加密结果
console.log(encrypted.toString())
上面代码中,我们定义了一个 16 字节的密钥(key
),一个 8 字节的偏移量(iv
),和要加密的数据(data
)。然后在使用 TripleDES.encrypt
方法进行加密,该方法的第一个参数是待加密的数据,第二个参数是密钥,第三个参数是可选的配置对象,我们使用 CBC 模式和 PKCS7 填充方式进行加密。
最后,我们使用 toString
方法输出加密结果。输出的加密结果是一个字符串,为了传输方便,可以使用 Base64 编码。
在解密之前,我们需要先将加密的结果字符串解码。
// 解码加密的结果
const encryptedBase64 = 'U2FsdGVkX1/Aj1AdyabUhS7TE9Suh+2YJpQAVs/ibjY='
const encryptedHex = CryptoJS.enc.Base64.parse(encryptedBase64)
const encryptedStr = encryptedHex.toString(CryptoJS.enc.Utf8)
// 解密
const decrypted = CryptoJS.TripleDES.decrypt(
{
ciphertext: encryptedHex
},
key,
{
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}
)
// 输出解密结果
console.log(decrypted.toString(CryptoJS.enc.Utf8))
上面代码中,我们使用 CryptoJS.enc.Base64.parse
方法将加密结果字符串解码,得到加密结果的字节数组。然后使用 toString
方法将字节数组转为字符串。
接下来,我们使用 TripleDES.decrypt
方法进行解密。该方法的第一个参数是一个对象,包含了将要被解密的字节数组(这里是加密结果的字节数组),第二个参数是密钥,第三个参数是可选的配置对象,我们使用 CBC 模式和 PKCS7 填充方式进行解密。
最后,我们使用 toString
方法输出解密结果。
在 JavaScript 中使用 SHA1 加解密依然需要依赖第三方库 crypto-js
。
先安装该库:
npm install crypto-js --save
接下来,我们来分别介绍 SHA1 的加密和解密。
import CryptoJS from 'crypto-js'
// 定义要加密的数据
const data = 'hello world'
// 加密
const encrypted = CryptoJS.SHA1(data)
// 输出加密结果
console.log(encrypted.toString())
上面代码中,我们定义了要加密的数据(data
)。然后在使用 SHA1
方法进行加密,该方法的参数是待加密的数据。
最后,我们使用 toString
方法输出加密结果。输出的加密结果同样是一个字符串,为了传输方便,可以使用 Base64 编码。
SHA1 加密是不可逆的,不支持解密。