🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
>[success] # readonly 1. `readonly` 会返回**原生对象的只读代理**都是不允许修改,它依然是一个`Proxy`,这是一个`proxy`的`set`方法被劫持,并且不能对其进行修改 2. `readonly`支持参数类型 * 普通对象; * `reactive`返回的对象; * `ref`的对象; 3. 在我们传递给其他组件数据时,往往希望其他组件使用我们传递的内容,但是不允许它们修改时,就可以使用`readonly` >[danger] ##### 案例 [参考](https://sfc.vuejs.org/#eNp9Ul+L00AQ/yrDvrTl2sTn0BP9DL7uSy7d1Nwl2WV3Uy0lICIWRNQDESz4ptUH/5xwCtVy92W6Nj75FZxssu3hgUnI7uz85vebmZ0ZuS2ENykYCchQs0ykoWY3aQ4wPCq05jncitIkOjmkxK6UWCdsH67M/CdYoN8g0TH0r1CgqSKZCG0jkkxwqWEGkoUjnqdT6OMu0smElRBLnkEHs+jUUHbfQkcsDosUQ6wgKKYL0e05EyKeKw1cJuMkD1M4rIktXXeGviLXAdyAslfnQTXVLT7iYtpgbRJdF1/jEIVvwx4XOZJh+bbqbs+pgu/D7weL6nK+l95cfv71ctWI/lk/NWePN+tF9X5pnp9uLt5U3141qtvFo83F0rz4aF5/cGqOw7PBBwcuW6r3Ojb4uob5sq7m5+bt1+r8nVl9N/Mf22dn1aelOX3iOOpIx1wn3ngDoOQOw9YJJkNbI34nbAodC+1AHCYpGwWgQzlGXKJ27fIoaftQWo22JxKvRua7m8HH1dXfH9XJXDXtNLUmsu0W/A393eCQPmkmZ5CFwjtWPMdBtUK0dShKAidNCc5QbVNyV2uhAt9XcVSP97HyuBz7uPMkFplkzGMqGxxJfk8xicSUtMlZDh8PJ0wOJMtHTDL5P85/oNd426JKUv4FWxhOJg==) ~~~html <template> <button @click="click"> 点击 </button> </template> <script> import { readonly ,reactive} from 'vue' export default { setup() { const original = reactive({ count: 0 }) const copy = readonly(original) function click(){ // 通过 original 修改 count,将会触发依赖 copy 的侦听器 original.count++ // 通过 copy 修改 count,将导致失败并出现警告 copy.count++ // 警告: "Set operation on key 'count' failed: target is readonly." } return { original, copy, click } } } </script> ~~~ >[danger] ##### ref 解包 1. `readonly `也能对`ref `进行解包,原理上和`reactiv `一样,当ref使用基本类型参数 并且作为`readonly `代理对象`value`时候 ~~~ const raw = { count: ref(123) } const copy = readonly(raw) console.log(raw.count.value) // 123 console.log(copy.count) // 123 ~~~ >[danger] ##### 使用场景 -- 组件传递 1. vue 官方建议是数据流保持单向传递,**尽可能将任何对响应式状态的变更都保持在供给方组件中**,为了防止其他人在子组件改变数据就可以使用`readonly` * [案例](https://sfc.vuejs.org/#eNqtU8Fu00AQ/ZWRL3aVxIar5URFfAAHjpiD42wSp/Z6tV4HIssS4kAkhJCQOHEGbkCRKqRApf4MpuHELzC7a29dUvVEFNne2Zk3b2beVNY9xtx1SSzfCgTJWBoJMgkpQHB/maQzTigcx8uILsg4tPRHaIGf82SR0CiVxpxtQmsSeF0AhgdeDwuPRcwTJhRukrGcC6iAk2iW03QDQ/yKRbImNcx5noGNdOyeqyGib12TSPJWjuSpcpyReVSmiC1tAHGO8ZRQUfitBQzWUBvq9l0QUTLnqIvEUFoI6IqEsSSrKDoV3pVU+HAH6iNZWyhC0frLTmhfVZjTxUs/6TUvKYLkFHQfnTVeGWZg0rkqAwzGeN/e1p0XR6KcGp69qLYSzZ5t+kc9tfbcQqkXPgLPzMYaWrrjoyxi7qrIKYpCZQrbiyK0/C53aGH35Tm0lkKwwve8Yh7LkawKN+cLD79cjoUkGXFJkY2mPH9SEI7AodWyUxgeGteEj3AqM8IJvw3zH9cD3LaoGkvpi+RQ3NNSCBzEcZwm8YkUsXyjihWvy+e7ZvsDqqrrba26FXg66r/p+2bZMp5j5WbCHYcrC4DYMOI/mK5ILMycQ9Hi+M7ReOJUUp3XJ966kiwR/iNbq8J+fG0DVO5hJV1quQ2oWoNvsl/JWDbN6UsYwPPg97N3+4ut3oafF59/vd3pnflz/qo5fdF8Od9vz5r3X/dnH5rdt2b7/fL16f7Tx+bNyz6OYqI3YTCQqNpFSuMhwdVkhEeKBP5PyAZs5WrDPEpSMvNBRHyBfklh5uBqeXQ/WaPTdWF413RL9cscDvetNxHN8YYFxJ1TeuoMt+xc/RcLQN8U) * 父组件 ~~~html <template> <Children @change="change" :original="copy"></Children> </template> <script> import { readonly ,reactive} from 'vue' import Children from './Children.vue' export default { components:{ Children, }, setup() { const original = reactive({ count: 0 }) const copy = readonly(original) function change(val){ original.count +=val } return { original, copy, change } } } </script> ~~~ * 子组件 ~~~html <template> <button @click="click"> 点击 {{original}} </button> </template> <script> import { readonly ,reactive} from 'vue' export default { props:{ original:{ type:Object, default:()=>({}) } }, emit:['change'], setup(props,{emit}) { function click(){ // 通过 copy 修改 count,将导致失败并出现警告 props.count++ // 警告: "Set operation on key 'count' failed: target is readonly." emit('change',1) } return { original:props.original, click } } } </script> ~~~ >[danger] ##### 官方参考 [## readonly](https://cn.vuejs.org/api/reactivity-core.html#readonly) [## 和响应式数据配合使用 provide 看这个](https://cn.vuejs.org/guide/components/provide-inject.html#working-with-reactivity)