2023-4-19 前端達人
Vue2.0使用Object.defineProperty
原理:通過使用 Object.defineProperty 來劫持對象屬性的 geter 和 seter 操作,當數據發生改變發出通知
// 數據 let data = { title: '', // 備份數據 _data: {} } // 定義特性 Object.defineProperty(data, 'title', { // 定義特性屬性或者特性方法 // 取值方法 get() { // console.log('get') // 注意:不能通過自身屬性取值 // return this.title // 返回備份的數據 return this._data.title; }, // 賦值方法 set(value) { // this指向對象 // 注意:不能為自身屬性賦值 // this.title = value // 我們可以向備份數據中存儲 this._data.title = value; // console.log('set') // 更新視圖 updateView(this._data) } }) // 視圖模板 let tpl = document.getElementById('app').innerHTML // 實現更新視圖的方法 function updateView(data) { // 處理模板 let html = tpl.replace(/{{(w+)}}/g, (match, $1) => { // 從data中獲取數據 return data[$1] || '' }) // 更新視圖 document.getElementById('app').innerHTML = html; }
![]()
使用ES6的新特性porxy
原理:通過ES6的新特性proxy來劫持數據,當數據改變時發出通知
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="yingaxiang" content="width=device-width, initial-scale=1.0"> <title>vue3.0數據雙向綁定</title> </head> <body> <div> <input type="text" id="input"> <span id="text"></span> </div> </body> </html> <script> var obj = {}; var obj1 = new Proxy(obj, { // target就是第一個參數obj, receive就是返回的obj(返回的proxy對象) get: function (target, key, receive) { // 返回該屬性值 return target[key]; }, set: function (target, key, newVal, receive) { // 執行賦值操作 target[key] = newVal; document.getElementById('text').innerHTML = target[key]; } }) document.addEventListener('keyup', function (e) { obj1[0] = e.target.value; }); </script>
![]()
總結:
Vue2.x版本中的雙向綁定不能檢測到下標的變化
proxy可以劫持整個對象,并返回一個新對象
未創建過vue腳手架得同學 或者從線上拉項目下來得同學 可以首先 查一下 當前版本
1:查看當前版本,如果是2開頭說明當前使用的是vue-cli2,3開頭的話就是vue-cli4
vue --version
2:如果無法識別vue命令說明沒有安裝vue-cli,使用以下說明進行安裝
安裝3.0版本: 目前新項目搭建腳手架默認安裝得是3.0版本
npm install -g vue-cli
如果是舊項目2.0版本到3.0切換得同學,即卸載當前版本,安裝另外的版本
從2.0升級到3.0:
npm uninstall -g vue-cli
npm install -g @vue/cli
如果想從新版本降到舊版本得同學 看這里?。?
從3.0降到2.0:
npm uninstall -g @vue/cli
npm install -g vue-cli
項目初始化
初始化,vue init <模板名稱(webpack比較常用)> [項目名稱]
vue init webpack cli2-test
2.0項目初始化參數介紹
//項目名稱 Project name ... //作者的信息,會默認從git中讀取信息 Project description ... Author ... //vue build的選項 1.runtime-compiler 2.runtime-only (一般選第一個就好) vue build ... //是否安裝vue-router,一般選用YES,省去手動創建路由 Install vue-router? .. //是否使用ESLint檢測代碼規范,規范可根據選項選擇不同的規范庫或者自己添加規范 use ESLint to link your code //是否寫單元測試 (一般不使用) Set up unit tests //是否使用Nightwatch來進行e2e測試 (2代表to e to e 點對點) Setup e2e test with Nightwatch? //使用npm或者yarn包管理工具 use npm use yarn
![]()
3.0初始化,vue create [項目名稱]
vue create cli3-test ?項目初始化參數介紹 //選擇一個配置方式 please pick a perset (一般選最后一個Manually select features(手動選擇特性) ) //選擇對于你的工程所需要的特性 (用空格選擇) check the features needed for your project ( ) Babel //轉碼器,可以將ES6代碼轉為ES5代碼,從而在現有環境執行。 ( ) TypeScript// TypeScript是一個JavaScript(后綴.js)的超集(后綴.ts)包含并擴展了 JavaScript 的語法,需要被編譯輸出為 JavaScript在瀏覽器運行,目前較少人再用 ( ) Progressive Web App (PWA) Support// 漸進式Web應用程序 ( ) Router // vue-router(vue路由) ( ) Vuex // vuex(vue的狀態管理模式) ( ) CSS Pre-processors // CSS 預處理器(如:less、sass) ( ) Linter / Formatter // 代碼風格檢查和格式化(如:ESlint) ( ) Unit Testing // 單元測試(unit tests) ( ) E2E Testing // e2e(end to end) 測試 //對應的配置文件單獨生成還是放在package.json里 where do you prefer placing config for babel //要不要把剛才自己選擇的配置保存下來 save this as a preset for future projects?
![]()
總結:
我們可以通過在項目根目錄下手動創建不同環境的配置文件,具體的環境變量名稱由package.json中運行參數決定,下面舉個例子添加development、production和uat版本的環境變量:
// .env.delelopment NODE_ENV=development VUE_APP_MODE=development BASE_URL=/develop // .env.production NODE_ENV=production VUE_APP_MODE=production BASE_URL=/api // .env.uat NODE_ENV=production VUE_APP_MODE=uat BASE_URL=/uat 不同得環境發不同的包 同學要配置得可以參考 // package.json ---- "scripts": { "serve": "vue-cli-service serve", "build:uat": "vue-cli-service build --mode uat", // 通過 --mode來運行不同的環境,自動識別到.env.uat配置文件 "build:production": "vue-cli-service build --mode production", "lint": "vue-cli-service lint" },
![]()
3.0版本中不同環境的webpack配置文件也沒有了(webpack.base.conf.js / webpack.dev.conf.js / webpack.prod.conf.js)
同樣,我們也可以再根目錄中創建vue.config.js文件來進行webpack和vue的一些配置
const path = require('path') module.exports = { publicPath: './', // 基本路徑,打包時加上. outputDir: process.env.outputDir, // 輸出文件目錄 lintOnSave: false, // eslint-loader 是否在保存的時候檢查 // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md // webpack配置 chainWebpack: (config) => { config.resolve.symlinks(true) }, configureWebpack: (config) => { if (process.env.VUE_APP_MODE === 'production') { // 為生產環境修改配置... config.mode = 'production' } else { // 為開發環境修改配置... config.mode = 'development' } Object.assign(config, { // 開發生產共同配置 resolve: { alias: { '@': path.resolve(__dirname, './src'), '@c': path.resolve(__dirname, './src/components'), '@p': path.resolve(__dirname, './src/views') } // 別名配置 } }) }, productionSourceMap: false, // 生產環境是否生成 sourceMap 文件 // css相關配置 css: { // extract: true, // 是否使用css分離插件 ExtractTextPlugin sourceMap: false, // 開啟 CSS source maps? loaderOptions: { css: {}, // 這里的選項會傳遞給 css-loader less: { modifyVars: { // less vars,customize ant design theme // 'primary-color': '#F5222D', // 'link-color': '#F5222D', // 'border-radius-base': '4px' }, // DO NOT REMOVE THIS LINE javascriptEnabled: true }, postcss: { plugins: [ // 把px單位換算成rem單位 require('postcss-pxtorem')({ rootValue: 75, // 換算的基數(設計圖750的根字體為32) selectorBlackList: ['.van-'], // 要忽略的選擇器并保留為px。 propList: ['*'], // 可以從px更改為rem的屬性。 minPixelValue: 2 // 設置要替換的最小像素值。 }), require('autoprefixer') ] // plugins: [ // require('autoprefixer') // ] } // 這里的選項會傳遞給 postcss-loader }, // css預設器配置項 詳見https://cli.vuejs.org/zh/config/#css-loaderoptions // modules: false, // 啟用 CSS modules for all css / pre-processor files. requireModuleExtension: true }, parallel: require('os').cpus().length > 1, // 是否為 Babel 或 TypeScript 使用 thread-loader。該選項在系統的 CPU 有多于一個內核時自動啟用,僅作用于生產構建。 pwa: {}, // PWA 插件相關配置 see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa // webpack-dev-server 相關配置 devServer: { open: false, // 自動打開瀏覽器 host: '0.0.0.0', // 允許外部ip訪問 port: 8000, // 端口 https: false, // 啟用https overlay: { warnings: true, errors: true }, // 錯誤、警告在頁面彈出 // proxy: 'http://localhost:4000' // 配置跨域處理,只有一個代理 proxy: { '/api': { target: '<url>', ws: true, changeOrigin: true }, '/foo': { target: '<other_url>' } }, // 配置多個代理 }, // 第三方插件配置 pluginOptions: {}
![]()
https://blog.csdn.net/qq_41328247/article/details/109286022
2.0 周期名稱
3.0 周期名稱
說明
beforeCreate
setup
組件創建之前
created
setup
組件創建完成
beforeMount
onBeforeMount
組件掛載之前
mounted
onMounted
組件掛載完成
beforeUpdate
onBeforeUpdate
數據更新,虛擬 DOM 打補丁之前
updated
onUpdated
數據更新,虛擬 DOM 渲染完成
beforeDestroy
onBeforeUnmount
組件銷毀之前
destroyed
onUnmounted
組件銷毀后
<template> <router-link to="/">點這里去首頁</router-link> <hr> <div class="home"> 這里是一個計數器 >>> <span class="red">{{count}}</span> <br> <button @click="countAdd">點擊加數字</button> </div> </template> <script> // 你需要使用到什么生命周期,就引出來什么生命周期 import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, ref } from 'vue' export default { // setup 函數,就相當于 vue 2.0 中的 created setup () { const count = ref(0) // 其他的生命周期都寫在這里 onBeforeMount (() => { count.value++ console.log('onBeforeMount', count.value) }) onMounted (() => { count.value++ console.log('onMounted', count.value) }) // 注意,onBeforeUpdate 和 onUpdated 里面不要修改值,會死循環的哦! onBeforeUpdate (() => { console.log('onBeforeUpdate', count.value) }) onUpdated (() => { console.log('onUpdated', count.value) }) onBeforeUnmount (() => { count.value++ console.log('onBeforeUnmount', count.value) }) onUnmounted (() => { count.value++ console.log('onUnmounted', count.value) }) // 定義一個函數,修改 count 的值。 const countAdd = () => { count.value++ } return { count, countAdd } } } </script> 首先,在 vue 3.0 中,生命周期是從 vue 中導出的,我們需要用到哪些,就導出哪些。
![]()
可能不少看官會認為多次一舉,但實則不然。vue 提供這么多的生命周期,有幾個是我們常用的?在大多數的組件中,我們用不到生命周期。即便是頁面級別的應用,可能用到最多的是 onMounted 即可。
當然,那些綁定時間的操作會用到解綁,因此會用到 onUnmounted。其它的生命周期,正常情況下是基本用不到的。所以,通過引入使用的這種設定,可以減少我們的最終編譯的項目的體積。而且,這樣的引入使用,更加的邏輯清晰。
其次,除 setup 之外,其他的生命周期函數,都是在 setup 里面直接書寫函數即可。
Vue2.x 版本啟動
npm run dev
Vue3.x 版本啟動
npm run serve
1.v-model
語法糖廢棄,改用modelValue
<input v-model="value" />
<input modelValue="value" />
2.棄用全局APInew Vue
,使用createApp
const app =?Vue.createApp({})
3.棄用Vue.prototype
,在Vue3中,我們可以使用如下定義方式
const app = Vue.createApp({})
app.config.globalProperties.$http = () => {}
4.全局方法現在全部在app實例上,例如:
`app.directive`,`app.use`等
5.現在你需要手動掛載根節點
main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
6.不能再使用Vue.nextTick
/this.$nextTick
,Vue3中你可以用:
import { nextTick } from 'vue'
nextTick(() => {
// something
})
7.Vue3允許template
設置key
。
8.正式棄用scopedSlots
正式棄用,舊的不去新的不來。
9.監聽數組變化需要使用deep
屬性,否則只能監聽到整個數組被替換。
10.棄用$children
,訪問子組件可以使用$ref
11.filter
被移除,我X,不能再使用|
了。
12.移除事件API,$on
,$once
,$off
不再使用。EventBus
方法也不再使用。
2.x 版本中,使用 Vue.set 來給對象新增一個屬性時,這個對象的所有 watcher 都會重新運行
3.x 版本中,只有依賴那個屬性的 watcher 才會重新運行。
藍藍設計的小編 http://www.syprn.cn