一、响应式数据创建
- ref()接受一个普通值,返回一个响应式的值
示例:
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
- reactive() 接受一个对象,返回一个响应式的对象。(响应式转换是“深层”的,无论嵌套多少层都会转换成响应式)
示例:
const count = ref(1)
const obj = reactive({ count })
// ref 会被解包
console.log(obj.count === count.value) // true
// 会更新 `obj.count`
count.value++
console.log(count.value) // 2
console.log(obj.count) // 2
// 也会更新 `count` ref
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3
- toRefs() 结构响应式数据,一般用在 props 传参上
示例:
import { toRefs } from 'vue'
const props = defineProps({
// 布局
layout: {
type: String as PropType<'1' | '2' | '3' | '4'>,
required: true,
default: '1',
},
// 标题
title: {
type: String as PropType<string>,
default: '',
},
})
const { title } = toRefs(props)
- computed() 计算属性
示例:
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误
- shallowRef() 创建一个响应式数据,同ref,此方法是一个浅层的作用
示例:
const state = shallowRef({ count: 1 })
// 不会触发更改
state.value.count = 2
// 会触发更改
state.value = { count: 2 }
- shallowReactive() 创建一个响应式对象,同reactive,此方法是一个浅层的作用
示例:
const state = shallowReactive({
foo: 1,
nested: {
bar: 2
}
})
// 更改状态自身的属性是响应式的
state.foo++
// ...但下层嵌套对象不会被转为响应式
isReactive(state.nested) // false
// 不是响应式的
state.nested.bar++
二、组件间通信
1.父传子 defineProps
父组件:
setup(props, context) { const status = ref(1); return { status }; },
子组件:
import { defineProps } from 'vue'
const props = defineProps({ status: Number })
2.子传父
const off = (data) => {
// 点击关闭按钮
context.emit('handle', data);
}
3.双向绑定更新
父组件:
<child v-model:a="a" v-model:b="b"></child>
子组件:
const handle = () => { emit("update:a", "更新父级的a值") emit("update:b", "更新父级的b值") }
3.provide / inject
provide:可以让我们指定想要提供给后代组件的数据或
inject:在任何后代组件中接收想要添加在这个组件上的数据,不管组件嵌套多深都可以直接拿来用
<script setup>
import { provide } from "vue"
provide("title", "哈哈哈")
</script>
<script setup>
import { inject } from "vue"
const title = inject("title") console.log(title) //哈哈哈
</script>
4.expose / ref
//import { defineExpose } from "vue";
defineExpose({
childName: "这是子组件的属性,
someMethod(){
console.log("这是子组件的方法")
}
})
父组件:
const RefChilde = ref(null)
RefChilde.value.方法
三、vue.config.js 配置解析
Vue CLI 官方文档:vue-cli-service
暴露了 inspect
命令用于审查解析好的 webpack
配置。那个全局的 vue 可执行程序同样提供了 inspect
命令,这个命令只是简单的把 vue-cli-service``inspect
代理到了你的项目中
基本配置
module.exports = {
productionSourceMap: false,
publicPath: './',
outputDir: 'dist',
assetsDir: 'assets',
devServer: { port: 8090, host: '0.0.0.0', https: false, open: true },
// 其他配置 ...
}
-
productionSourceMap:生产环境是否要生成
sourceMap
-
publicPath:部署应用包时的基本 URL,用法和
webpack
本身的output.publicPath
一致 - 可以通过三元运算去配置
dev
和prod
环境,publicPath: process.env.NODE_ENV === 'production' ? '/prod/' : './'
-
outputDir:
build
时输出的文件目录 - assetsDir: 放置静态文件夹目录
-
devServer: dev环境下,
webpack-dev-server
相关配置 - port: 开发运行时的端口
-
host: 开发运行时域名,设置成
'0.0.0.0'
,在同一个局域网下,如果你的项目在运行,同时可以通过你的http://ip:port/...访问你的项目 -
https: 是否启用
https
-
open:
npm run serve
时是否直接打开浏览器
一些常见的配置
1 修改enter文件
`webpack` 默认的 `entry` 入口是 `scr/main.ts`
config.entryPoints.clear(); // 清空默认入口
config.entry('test').add(getPath('./test/main.ts')); // 重新设置
2 DefinePlugin
定义全局全局变量,`DefinePlugin` 是 `webpack` 已经默认配置的,我们可以对参数进行修改
config.plugin('define').tap(args => [{
...args,
"window.isDefine": JSON.stringify(true),
}]);
3 自定义filename 及 chunkFilename
自定义打包后js文件的路径及文件名字
config.output.filename('./js/[name].[chunkhash:8].js');
config.output.chunkFilename('./js/[name].[chunkhash:8].js');
4 修改html-webpack-plugin参数
`html-webpack-plugin` 是 `webpack` 已经默认配置的,默认的源模版文件是 `public/index.html` ;我们可以对其参数进行修改
config.plugin('html')
.tap(options => [{
template: '../../index.html' // 修改源模版文件
title: 'test',
}]);
5 设置别名alias
`webpack`默认是将`src`的别名设置为`@`, 此外,我们可以进行添加
config.resolve.alias
.set('@', resolve('src'))
.set('api', resolve('src/apis'))
.set('common', resolve('src/common'))
附上一份vue.config.js的配置
const path = require('path');
const HotHashWebpackPlugin = require('hot-hash-webpack-plugin');
const WebpackBar = require('webpackbar');
const resolve = (dir) => path.join(__dirname, '.', dir);
module.exports = {
productionSourceMap: false,
publicPath: './',
outputDir: 'dist',
assetsDir: 'assets',
devServer: {
port: 9999,
host: '0.0.0.0',
https: false,
open: true
},
chainWebpack: (config) => {
const types = ['vue-modules', 'vue', 'normal-modules', 'normal'];
types.forEach(type => {
let rule = config.module.rule('less').oneOf(type)
rule.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [path.resolve(__dirname, './lessVariates.less')]
});
});
config.resolve.alias
.set('@', resolve('src'))
.set('api', resolve('src/apis'))
.set('common', resolve('src/common'))
config.module.rule('images').use('url-loader')
.tap(options => ({
name: './assets/images/[name].[ext]',
quality: 85,
limit: 0,
esModule: false,
}));
config.module.rule('svg')
.test(/.svg$/)
.include.add(resolve('src/svg'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader');
config.plugin('define').tap(args => [{
...args,
"window.isDefine": JSON.stringify(true)
}]);
// 生产环境配置
if (process.env.NODE_ENV === 'production') {
config.output.filename('./js/[name].[chunkhash:8].js');
config.output.chunkFilename('./js/[name].[chunkhash:8].js');
config.plugin('extract-css').tap(args => [{
filename: 'css/[name].[contenthash:8].css',
chunkFilename: 'css/[name].[contenthash:8].css'
}]);
config.plugin('hotHash').use(HotHashWebpackPlugin, [{ version : '1.0.0'}]);
config.plugin('webpackBar').use(WebpackBar);
config.optimization.minimize(true)
.minimizer('terser')
.tap(args => {
let { terserOptions } = args[0];
terserOptions.compress.drop_console = true;
terserOptions.compress.drop_debugger = true;
return args
});
config.optimization.splitChunks({
cacheGroups: {
common: {
name: 'common',
chunks: 'all',
minSize: 1,
minChunks: 2,
priority: 1
},
vendor: {
name: 'chunk-libs',
chunks: 'all',
test: /[\/]node_modules[\/]/,
priority: 10
}
}
});
}
}
};